1 /** \file lvfreetypeface.h
2     \brief FreeType font interface
3 
4     CoolReader Engine
5 
6 
7     (c) Vadim Lopatin, 2000-2006
8     This source code is distributed under the terms of
9     GNU General Public License.
10 
11     See LICENSE file for details.
12 
13 */
14 
15 #ifndef __LV_FREETYPEFACE_H_INCLUDED__
16 #define __LV_FREETYPEFACE_H_INCLUDED__
17 
18 
19 #include "../../include/crsetup.h"
20 #include "../../include/lvfont.h"
21 #include "../../include/lvthread.h"
22 #include "lvfontglyphcache.h"
23 #include "lvfontdef.h"
24 #include "lvfontcache.h"
25 
26 // define to filter out all fonts except .ttf
27 //#define LOAD_TTF_FONTS_ONLY
28 // DEBUG ONLY
29 #if 0
30 #define USE_FREETYPE 1
31 #define USE_FONTCONFIG 1
32 //#define DEBUG_FONT_SYNTHESIS 1
33 //#define DEBUG_FONT_MAN 1
34 //#define DEBUG_FONT_MAN_LOG_FILE "/tmp/font_man.log"
35 #endif
36 
37 #if (USE_FREETYPE == 1)
38 
39 #include <ft2build.h>
40 #include FT_FREETYPE_H
41 
42 #if USE_HARFBUZZ == 1
43 
44 #include <hb.h>
45 #include <hb-ft.h>
46 #include "../../include/lvhashtable.h"
47 
48 #endif
49 
50 // Use Freetype embolden API instead of LVFontBoldTransform to
51 // make fake bold (for fonts that do not provide a bold face).
52 // This gives a chance to get them working with Harfbuzz, even if
53 // they won't look as nice as if they came with a real bold font.
54 #define USE_FT_EMBOLDEN
55 
56 #define CACHED_UNSIGNED_METRIC_NOT_SET 0xFFFF
57 class LVFontGlyphUnsignedMetricCache
58 {
59 private:
60     static const int COUNT = 360;
61     lUInt16 * ptrs[COUNT]; //support up to 0X2CFFF=360*512-1
62 public:
get(lChar32 ch)63     lUInt16 get( lChar32 ch )
64     {
65         FONT_GLYPH_CACHE_GUARD
66         int inx = (ch>>9) & 0x1ff;
67         if (inx >= COUNT) return CACHED_UNSIGNED_METRIC_NOT_SET;
68         lUInt16 * ptr = ptrs[inx];
69         if ( !ptr )
70             return CACHED_UNSIGNED_METRIC_NOT_SET;
71         return ptr[ch & 0x1FF ];
72     }
put(lChar32 ch,lUInt16 m)73     void put( lChar32 ch, lUInt16 m )
74     {
75         FONT_GLYPH_CACHE_GUARD
76         int inx = (ch>>9) & 0x1ff;
77         if (inx >= COUNT) return;
78         lUInt16 * ptr = ptrs[inx];
79         if ( !ptr ) {
80             ptr = new lUInt16[512];
81             ptrs[inx] = ptr;
82             memset( ptr, CACHED_UNSIGNED_METRIC_NOT_SET, sizeof(lUInt16) * 512 );
83         }
84         ptr[ ch & 0x1FF ] = m;
85     }
clear()86     void clear()
87     {
88         FONT_GLYPH_CACHE_GUARD
89         for ( int i=0; i<360; i++ ) {
90             if ( ptrs[i] )
91                 delete [] ptrs[i];
92             ptrs[i] = NULL;
93         }
94     }
LVFontGlyphUnsignedMetricCache()95     LVFontGlyphUnsignedMetricCache()
96     {
97         memset( ptrs, 0, 360*sizeof(lUInt16*) );
98     }
~LVFontGlyphUnsignedMetricCache()99     ~LVFontGlyphUnsignedMetricCache()
100     {
101         clear();
102     }
103 };
104 
105 #define CACHED_SIGNED_METRIC_NOT_SET 0x7FFF
106 #define CACHED_SIGNED_METRIC_SHIFT 0x8000
107 class LVFontGlyphSignedMetricCache : public LVFontGlyphUnsignedMetricCache
108 {
109 public:
get(lChar32 ch)110     lInt16 get( lChar32 ch )
111     {
112         return (lInt16) ( LVFontGlyphUnsignedMetricCache::get(ch) - CACHED_SIGNED_METRIC_SHIFT );
113     }
put(lChar32 ch,lInt16 m)114     void put( lChar32 ch, lInt16 m )
115     {
116         LVFontGlyphUnsignedMetricCache::put(ch, (lUInt16)( m + CACHED_SIGNED_METRIC_SHIFT) );
117     }
118 };
119 
120 class LVFreeTypeFace : public LVFont {
121 protected:
122     LVMutex &_mutex;
123     lString8 _fileName;
124     lString8 _faceName;
125     css_font_family_t _fontFamily;
126     FT_Library _library;
127     FT_Face _face;
128     FT_GlyphSlot _slot;
129     FT_Matrix _matrix; // helper matrix for fake italic metrics
130     int _size; // caracter height in pixels
131     int _height; // full line height in pixels
132     int _hyphen_width;
133     int _baseline;
134     int _weight;
135     int _italic;
136     LVFontGlyphUnsignedMetricCache _wcache;
137     LVFontGlyphSignedMetricCache _lsbcache; // glyph left side bearing cache
138     LVFontGlyphSignedMetricCache _rsbcache; // glyph right side bearing cache
139     LVFontLocalGlyphCache _glyph_cache;
140     bool _drawMonochrome;
141     hinting_mode_t _hintingMode;
142     shaping_mode_t _shapingMode;
143     bool _fallbackFontIsSet;
144     LVFontRef _fallbackFont;
145     /**
146      * @brief Fallback mask for this fallback font.
147      * 0 - for normal (not fallback) font
148      * <any> - A mask with only one bit set, the number of which corresponds to the number in the fallback font chain.
149      */
150     lUInt32 _fallback_mask;
151     bool           _embolden; // fake/synthetized bold
152     bool           _allowKerning;
153     FT_Pos         _embolden_half_strength; // for emboldening with Harfbuzz
154     int _features; // requested OpenType features bitmap
155 #if USE_HARFBUZZ == 1
156     hb_font_t *_hb_font;
157     hb_buffer_t *_hb_buffer;
158     LVArray<hb_feature_t> _hb_features;
159     // For use with SHAPING_MODE_HARFBUZZ:
160     LVFontLocalGlyphCache _glyph_cache2;
161     // For use with SHAPING_MODE_HARFBUZZ_LIGHT:
162     LVHashTable<struct LVCharTriplet, struct LVCharPosInfo> _width_cache2;
163 #endif
164 public:
165 
166     // fallback font support
167 
getFallbackMask()168     virtual lUInt32 getFallbackMask() const {
169         return _fallback_mask;
170     }
171 
setFallbackMask(lUInt32 mask)172     virtual void setFallbackMask(lUInt32 mask) {
173         _fallback_mask = mask;
174     }
175 
176     /// set fallback font for this font
177     virtual void setFallbackFont(LVFontRef font);
178 
179     /// get fallback font for this font
180     virtual LVFont *getFallbackFont(lUInt32 fallbackPassMask);
181 
182     /// returns font weight
getWeight()183     virtual int getWeight() const { return _weight; }
184 
185     /// returns italic flag
getItalic()186     virtual int getItalic() const { return _italic; }
187 
188     /// sets face name
setFaceName(lString8 face)189     virtual void setFaceName(lString8 face) { _faceName = face; }
190 
getMutex()191     LVMutex &getMutex() { return _mutex; }
192 
getLibrary()193     FT_Library getLibrary() { return _library; }
194 
195     LVFreeTypeFace(LVMutex &mutex, FT_Library library, LVFontGlobalGlyphCache *globalCache);
196 
197     virtual ~LVFreeTypeFace();
198 
199     virtual void clearCache();
200 
201     virtual int getHyphenWidth();
202 
203     /// get kerning mode: true==ON, false=OFF
getKerning()204     virtual bool getKerning() const { return _allowKerning; }
205 
206     /// set kerning mode: true==ON, false=OFF
207     virtual void setKerning(bool kerningEnabled);
208 
209     /// sets current hinting mode
210     virtual void setHintingMode(hinting_mode_t mode);
211 
212     /// returns current hinting mode
getHintingMode()213     virtual hinting_mode_t getHintingMode() const { return _hintingMode; }
214 
215     /// sets current shaping mode
216     virtual void setShapingMode( shaping_mode_t shapingMode );
217 
218     /// returns current kerning mode
getShapingMode()219     virtual shaping_mode_t getShapingMode() const { return _shapingMode; }
220 
221     /// get bitmap mode (true=bitmap, false=antialiased)
getBitmapMode()222     virtual bool getBitmapMode() { return _drawMonochrome; }
223 
224     /// set bitmap mode (true=bitmap, false=antialiased)
225     virtual void setBitmapMode(bool drawBitmap);
226 
227     /// get OpenType features (bitmap)
getFeatures()228     virtual int getFeatures() const { return _features; }
229 
230     /// set OpenType features (bitmap)
231     virtual void setFeatures( int features );
232 
233     void setEmbolden();
234 
235     bool loadFromBuffer(LVByteArrayRef buf, int index, int size, css_font_family_t fontFamily,
236                         bool monochrome, bool italicize);
237 
238     bool loadFromFile(const char *fname, int index, int size, css_font_family_t fontFamily,
239                       bool monochrome, bool italicize);
240 
241     /** \brief get glyph info
242         \param glyph is pointer to glyph_info_t struct to place retrieved info
243         \return true if glyh was found
244     */
245     virtual bool getGlyphInfo(lUInt32 code, glyph_info_t *glyph, lChar32 def_char = 0, lUInt32 fallbackPassMask = 0);
246 /*
247   // USE GET_CHAR_FLAGS instead
248     inline int calcCharFlags( lChar32 ch )
249     {
250         switch ( ch ) {
251         case 0x0020:
252             return LCHAR_IS_SPACE | LCHAR_ALLOW_WRAP_AFTER;
253         case UNICODE_SOFT_HYPHEN_CODE:
254             return LCHAR_ALLOW_WRAP_AFTER;
255         case '-':
256             return LCHAR_DEPRECATED_WRAP_AFTER;
257         case '\r':
258         case '\n':
259             return LCHAR_IS_SPACE | LCHAR_IS_EOL | LCHAR_ALLOW_WRAP_AFTER;
260         default:
261             return 0;
262         }
263     }
264   */
265 
266     /**
267      * @brief Check font for compatibility with language with langCode
268      * @param langCode language code, for example, "en" - English, "ru" - Russian
269      * @return true if font contains all glyphs for given language, false otherwise.
270      */
271     virtual bool checkFontLangCompat(const lString8 &langCode);
272 
273     /** \brief measure text
274         \param text is text string pointer
275         \param len is number of characters to measure
276         \return number of characters before max_width reached
277     */
278     virtual lUInt16 measureText(
279             const lChar32 *text, int len,
280             lUInt16 *widths,
281             lUInt8 *flags,
282             int max_width,
283             lChar32 def_char,
284             TextLangCfg * lang_cfg = NULL,
285             int letter_spacing = 0,
286             bool allow_hyphenation = true,
287             lUInt32 hints = 0,
288             lUInt32 fallbackPassMask = 0
289     );
290 
291     /** \brief measure text
292         \param text is text string pointer
293         \param len is number of characters to measure
294         \return width of specified string
295     */
296     virtual lUInt32 getTextWidth(
297             const lChar32 *text, int len, TextLangCfg * lang_cfg = NULL
298     );
299 
300     /** \brief get glyph item
301         \param code is unicode character
302         \return glyph pointer if glyph was found, NULL otherwise
303     */
304     virtual LVFontGlyphCacheItem *getGlyph(lUInt32 ch, lChar32 def_char = 0, lUInt32 fallbackPassMask = 0);
305 
306 //    /** \brief get glyph image in 1 byte per pixel format
307 //        \param code is unicode character
308 //        \param buf is buffer [width*height] to place glyph data
309 //        \return true if glyph was found
310 //    */
311 //    virtual bool getGlyphImage(lUInt16 ch, lUInt8 * bmp, lChar32 def_char=0)
312 //    {
313 //        LVFontGlyphCacheItem * item = getGlyph(ch);
314 //        if ( item )
315 //            memcpy( bmp, item->bmp, item->bmp_width * item->bmp_height );
316 //        return item;
317 //    }
318 
319     /// returns font baseline offset
getBaseline()320     virtual int getBaseline() {
321         return _baseline;
322     }
323 
324     /// returns font height
getHeight()325     virtual int getHeight() const {
326         return _height;
327     }
328 
329     /// returns font character size
getSize()330     virtual int getSize() const {
331         return _size;
332     }
333 
334     /// returns char width
335     virtual int getCharWidth(lChar32 ch, lChar32 def_char = '?');
336 
337     /// returns char glyph left side bearing
338     int getLeftSideBearing( lChar32 ch, bool negative_only=false, bool italic_only=false );
339 
340     /// returns char glyph right side bearing
341     virtual int getRightSideBearing( lChar32 ch, bool negative_only=false, bool italic_only=false );
342 
343     /// retrieves font handle
GetHandle()344     virtual void *GetHandle() {
345         return NULL;
346     }
347 
348     /// returns font typeface name
getTypeFace()349     virtual lString8 getTypeFace() const {
350         return _faceName;
351     }
352 
353     /// returns font family id
getFontFamily()354     virtual css_font_family_t getFontFamily() const {
355         return _fontFamily;
356     }
357 
kerningEnabled()358     virtual bool kerningEnabled() {
359 #if (ALLOW_KERNING==1)
360     #if USE_HARFBUZZ==1
361         return _allowKerning;
362 #else
363         return _allowKerning && FT_HAS_KERNING( _face );
364     #endif
365 #else
366         return false;
367 #endif
368     }
369 
370     /// draws text string
371     virtual int DrawTextString(LVDrawBuf *buf, int x, int y,
372                                const lChar32 *text, int len,
373                                lChar32 def_char, lUInt32 *palette = NULL,
374                                bool addHyphen = false, TextLangCfg * lang_cfg = NULL,
375                                lUInt32 flags = 0, int letter_spacing = 0, int width=-1,
376                                int text_decoration_back_gap = 0,
377                                lUInt32 fallbackPassMask = 0);
378 
379     /// returns true if font is empty
IsNull()380     virtual bool IsNull() const {
381         return _face == NULL;
382     }
383 
384     virtual bool operator!() const {
385         return _face == NULL;
386     }
387 
388     virtual void Clear();
389 protected:
390     void updateTransform();
391     FT_UInt getCharIndex(lUInt32 code, lChar32 def_char);
392 #if USE_HARFBUZZ==1
393     LVFontGlyphCacheItem *getGlyphByIndex(lUInt32 index);
394     lChar32 filterChar(lChar32 code, lChar32 def_char=0);
395     bool hbCalcCharWidth(struct LVCharPosInfo *posInfo, const struct LVCharTriplet &triplet,
396                          lChar32 def_char, lUInt32 fallbackPassMask);
397     bool setHBFeatureValue(const char * tag, uint32_t value);
398     bool addHBFeature(const char * tag);
399     bool delHBFeature(const char * tag);
400     void setupHBFeatures();
401 #endif
402 };
403 
404 #endif  // (USE_FREETYPE==1)
405 
406 #endif  // __LV_FREETYPEFACE_H_INCLUDED__
407