1 /** @file lvfont.h
2     @brief font interface
3 
4     CoolReader Engine
5 
6     (c) Vadim Lopatin, 2000-2006
7 
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_FONT_H_INCLUDED__
16 #define __LV_FONT_H_INCLUDED__
17 
18 #include "crsetup.h"
19 #include "lvstring.h"
20 #include "lvref.h"
21 #include "lvdrawbuf.h"
22 #include "cssdef.h"
23 
24 #define MAX_LINE_CHARS 2048
25 #define MAX_LINE_WIDTH 2048
26 #define MAX_LETTER_SPACING MAX_LINE_WIDTH/2
27 
28 enum hinting_mode_t {
29     HINTING_MODE_DISABLED = 0,
30     HINTING_MODE_BYTECODE_INTERPRETOR,
31     HINTING_MODE_AUTOHINT
32 };
33 
34 enum shaping_mode_t {
35     SHAPING_MODE_FREETYPE = 0,
36     SHAPING_MODE_HARFBUZZ_LIGHT,
37     SHAPING_MODE_HARFBUZZ
38 };
39 
40 // Hint flags for measuring and drawing (some used only with full Harfbuzz)
41 // These 4 translate (after mask & shift) from LTEXT_WORD_* equivalents
42 // (see lvtextfm.h). Keep them in sync.
43 #define LFNT_HINT_DIRECTION_KNOWN        0x0001 /// segment direction is known
44 #define LFNT_HINT_DIRECTION_IS_RTL       0x0002 /// segment direction is RTL
45 #define LFNT_HINT_BEGINS_PARAGRAPH       0x0004 /// segment is at start of paragraph
46 #define LFNT_HINT_ENDS_PARAGRAPH         0x0008 /// segment is at end of paragraph
47 
48 // These 4 translate from LTEXT_TD_* equivalents (see lvtextfm.h). Keep them in sync.
49 #define LFNT_DRAW_UNDERLINE              0x1000 /// underlined text
50 #define LFNT_DRAW_OVERLINE               0x2000 /// overlined text
51 #define LFNT_DRAW_LINE_THROUGH           0x4000 /// striked through text
52 #define LFNT_DRAW_DECORATION_MASK        0x7000
53 
54 // CSS font-variant and font-feature-settings properties:
55 //   https://drafts.csswg.org/css-fonts-3/#propdef-font-variant
56 //   https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant
57 // OpenType feature tags (to be provided to HarfBuzz)
58 //   https://en.wikipedia.org/wiki/List_of_typographic_features
59 //   https://docs.microsoft.com/en-us/typography/opentype/spec/featurelist
60 // See https://github.com/koreader/koreader/issues/5821#issuecomment-596243758
61 // Random notes:
62 // - common-ligatures : 'liga' + 'clig'  (the keyword 'normal' activates these ligatures)
63 //   and 'rlig' ("required ligatures, e.g. for arabic) are enabled by default by Harfbuzz
64 // - discretionary-ligatures : 'dlig'   (type designer choices) is not enabled by default
65 // - diagonal-fractions : 'frac' (enabling also 'numr' + 'dnom' seems not needed,
66 //   numr or dnom standalone just make the / more oblique)
67 // - stacked-fractions: "/" becomes horizontal
68 // - jis90 'jp90' is said to be the default in fonts. Other jp* replace this one.
69 // - Not supported (because no room and because they require some args, which
70 //   would complicate parsing and storing):
71 //   CSS font-variant-alternates:
72 //       stylistic()
73 //       styleset()
74 //       character-variant()
75 //       swash()
76 //       ornaments()
77 //       annotation()
78 
79 // OpenType features to request
80 // Max 31 bits. We need "signed int features" to have -1 for non-instantiated fonts)
81 #define LFNT_OT_FEATURES_NORMAL 0x00000000
82 
83 // #define LFNT_OT_FEATURES_P_LIGA 0x000000XX // +liga +clig enabled by default  (font-variant-ligatures: common-ligatures)
84 // #define LFNT_OT_FEATURES_P_CALT 0x000000XX // +calt       enabled by default  (font-variant-ligatures: contextual)
85 #define LFNT_OT_FEATURES_M_LIGA 0x00000001 // -liga -clig   (font-variant-ligatures: no-common-ligatures)
86 #define LFNT_OT_FEATURES_M_CALT 0x00000002 // -calt         (font-variant-ligatures: no-contextual)
87 #define LFNT_OT_FEATURES_P_DLIG 0x00000004 // +dlig         (font-variant-ligatures: discretionary-ligatures)
88 #define LFNT_OT_FEATURES_M_DLIG 0x00000008 // -dlig         (font-variant-ligatures: no-discretionary-ligatures)
89 #define LFNT_OT_FEATURES_P_HLIG 0x00000010 // +hlig         (font-variant-ligatures: historical-ligatures)
90 #define LFNT_OT_FEATURES_M_HLIG 0x00000020 // -hlig         (font-variant-ligatures: no-historical-ligatures)
91 
92 #define LFNT_OT_FEATURES_P_HIST 0x00000040 // +hist         (font-variant-alternates: historical-forms)
93 #define LFNT_OT_FEATURES_P_RUBY 0x00000080 // +ruby         (font-variant-east-asian: ruby)
94 
95 #define LFNT_OT_FEATURES_P_SMCP 0x00000100 // +smcp         (font-variant-caps: small-caps)
96 #define LFNT_OT_FEATURES_P_C2SC 0x00000200 // +c2sc +smcp   (font-variant-caps: all-small-caps)
97 #define LFNT_OT_FEATURES_P_PCAP 0x00000400 // +pcap         (font-variant-caps: petite-caps)
98 #define LFNT_OT_FEATURES_P_C2PC 0x00000800 // +c2pc +pcap   (font-variant-caps: all-petite-caps)
99 #define LFNT_OT_FEATURES_P_UNIC 0x00001000 // +unic         (font-variant-caps: unicase)
100 #define LFNT_OT_FEATURES_P_TITL 0x00002000 // +titl         (font-variant-caps: titling-caps)
101 #define LFNT_OT_FEATURES_P_SUPS 0x00004000 // +sups         (font-variant-position: super)
102 #define LFNT_OT_FEATURES_P_SUBS 0x00008000 // +subs         (font-variant-position: sub)
103 
104 #define LFNT_OT_FEATURES_P_LNUM 0x00010000 // +lnum         (font-variant-numeric: lining-nums)
105 #define LFNT_OT_FEATURES_P_ONUM 0x00020000 // +onum         (font-variant-numeric: oldstyle-nums)
106 #define LFNT_OT_FEATURES_P_PNUM 0x00040000 // +pnum         (font-variant-numeric: proportional-nums)
107 #define LFNT_OT_FEATURES_P_TNUM 0x00080000 // +tnum         (font-variant-numeric: tabular-nums)
108 #define LFNT_OT_FEATURES_P_ZERO 0x00100000 // +zero         (font-variant-numeric: slashed-zero)
109 #define LFNT_OT_FEATURES_P_ORDN 0x00200000 // +ordn         (font-variant-numeric: ordinal)
110 #define LFNT_OT_FEATURES_P_FRAC 0x00400000 // +frac         (font-variant-numeric: diagonal-fractions)
111 #define LFNT_OT_FEATURES_P_AFRC 0x00800000 // +afrc         (font-variant-numeric: stacked-fractions)
112 
113 #define LFNT_OT_FEATURES_P_SMPL 0x01000000 // +smpl         (font-variant-east-asian: simplified)
114 #define LFNT_OT_FEATURES_P_TRAD 0x02000000 // +trad         (font-variant-east-asian: traditional)
115 #define LFNT_OT_FEATURES_P_FWID 0x04000000 // +fwid         (font-variant-east-asian: full-width)
116 #define LFNT_OT_FEATURES_P_PWID 0x08000000 // +pwid         (font-variant-east-asian: proportional-width)
117 #define LFNT_OT_FEATURES_P_JP78 0x10000000 // +jp78         (font-variant-east-asian: jis78)
118 #define LFNT_OT_FEATURES_P_JP83 0x20000000 // +jp83         (font-variant-east-asian: jis83)
119 #define LFNT_OT_FEATURES_P_JP04 0x40000000 // +jp04         (font-variant-east-asian: jis04)
120 // No more room for: (let's hope it's really the default in fonts)
121 // #define LFNT_OT_FEATURES_P_JP90 0x80000000 // +jp90      (font-variant-east-asian: jis90)
122 
123 
124 enum font_antialiasing_t {
125     font_aa_none,
126     font_aa_big,
127     font_aa_all
128 };
129 
130 struct LVFontGlyphCacheItem;
131 class TextLangCfg;
132 
133 class LVFont;
134 typedef LVProtectedFastRef<LVFont> LVFontRef;
135 
136 /** \brief base class for fonts
137 
138     implements single interface for font of any engine
139 */
140 class LVFont : public LVRefCounter {
141 protected:
142     int _visual_alignment_width;
143 public:
144     lUInt32 _hash;
145     /// glyph properties structure
146     struct glyph_info_t {
147         lUInt16 blackBoxX;  ///< 0: width of glyph
148         lUInt16 blackBoxY;  ///< 1: height of glyph black box
149         lInt16  originX;    ///< 2: X origin for glyph (left side bearing)
150         lInt16  originY;    ///< 3: Y origin for glyph
151         lUInt16 width;      ///< 4: full advance width of glyph
152         lInt16  rsb;        ///< 5: right side bearing
153     };
154 
155     /// hyphenation character
getHyphChar()156     virtual lChar32 getHyphChar() { return UNICODE_SOFT_HYPHEN_CODE; }
157 
158     /// hyphen width
getHyphenWidth()159     virtual int getHyphenWidth() { return getCharWidth(getHyphChar()); }
160 
161     /**
162      * Max width of -/./,/!/? to use for visial alignment by width
163      */
164     virtual int getVisualAligmentWidth();
165 
166     /** \brief get glyph info
167         \param code is unicode character code
168         \param glyph is pointer to glyph_info_t struct to place retrieved info
169         \param def_char replacement char if glyph for code not found for this font
170         \param fallbackPassMask bitmask of processed fallback fonts
171         \return true if glyph was found
172     */
173     virtual bool getGlyphInfo(lUInt32 code, glyph_info_t *glyph, lChar32 def_char = 0, lUInt32 fallbackPassMask = 0) = 0;
174 
175     /** \brief measure text
176         \param text is text string pointer
177         \param len is number of characters to measure
178         \param max_width is maximum width to measure line
179         \param def_char is character to replace absent glyphs in font
180         \param letter_spacing is number of pixels to add between letters
181         \param hints: hint flags (direction, begin/end of paragraph, for Harfbuzz - unrelated to font hinting)
182         \param fallbackPassMask bitmask of processed fallback fonts
183         \return number of characters before max_width reached
184     */
185     virtual lUInt16 measureText(
186             const lChar32 *text, int len,
187             lUInt16 *widths,
188             lUInt8 *flags,
189             int max_width,
190             lChar32 def_char,
191             TextLangCfg * lang_cfg = NULL,
192             int letter_spacing = 0,
193             bool allow_hyphenation = true,
194             lUInt32 hints = 0,
195             lUInt32 fallbackPassMask = 0
196     ) = 0;
197 
198     /** \brief measure text
199         \param text is text string pointer
200         \param len is number of characters to measure
201         \return width of specified string
202     */
203     virtual lUInt32 getTextWidth(
204             const lChar32 *text, int len, TextLangCfg * lang_cfg = NULL
205     ) = 0;
206 
207 //    /** \brief get glyph image in 1 byte per pixel format
208 //        \param code is unicode character
209 //        \param buf is buffer [width*height] to place glyph data
210 //        \return true if glyph was found
211 //    */
212 //    virtual bool getGlyphImage(lUInt32 code, lUInt8 * buf, lChar32 def_char=0) = 0;
213     /** \brief get glyph item
214         \param ch is unicode character code
215         \param def_char replacement char if glyph for ch not found for this font
216         \param fallbackPassMask bitmask of processed fallback fonts
217         \return glyph pointer if glyph was found, NULL otherwise
218     */
219     virtual LVFontGlyphCacheItem *getGlyph(lUInt32 ch, lChar32 def_char = 0, lUInt32 fallbackPassMask = 0) = 0;
220 
221     /// returns font baseline offset
222     virtual int getBaseline() = 0;
223 
224     /// returns font height including normal interline space
225     virtual int getHeight() const = 0;
226 
227     /// returns font character size
228     virtual int getSize() const = 0;
229 
230     /// returns font weight
231     virtual int getWeight() const = 0;
232 
233     /// returns italic flag
234     virtual int getItalic() const = 0;
235 
236     /// returns char glyph advance width
237     virtual int getCharWidth( lChar32 ch, lChar32 def_char=0 ) = 0;
238 
239     /// returns char glyph left side bearing
240     virtual int getLeftSideBearing( lChar32 ch, bool negative_only=false, bool italic_only=false ) = 0;
241 
242     /// returns char glyph right side bearing
243     virtual int getRightSideBearing( lChar32 ch, bool negative_only=false, bool italic_only=false ) = 0;
244 
245     /// retrieves font handle
246     virtual void *GetHandle() = 0;
247 
248     /// returns font typeface name
249     virtual lString8 getTypeFace() const = 0;
250 
251     /// returns font family id
252     virtual css_font_family_t getFontFamily() const = 0;
253 
254     /// draws text string (returns x advance)
255     virtual int DrawTextString( LVDrawBuf * buf, int x, int y,
256                        const lChar32 * text, int len,
257                        lChar32 def_char, lUInt32 * palette = NULL,
258                        bool addHyphen = false, TextLangCfg * lang_cfg = NULL,
259                        lUInt32 flags=0, int letter_spacing=0, int width=-1,
260                        int text_decoration_back_gap=0,
261                        lUInt32 fallbackPassMask = 0) = 0;
262 
263     /// constructor
LVFont()264     LVFont() : _visual_alignment_width(-1), _hash(0) {}
265 
266     /// get bitmap mode (true=monochrome bitmap, false=antialiased)
getBitmapMode()267     virtual bool getBitmapMode() { return false; }
268 
269     /// set bitmap mode (true=monochrome bitmap, false=antialiased)
setBitmapMode(bool)270     virtual void setBitmapMode(bool) {}
271 
272     /// get OpenType features (bitmap)
getFeatures()273     virtual int getFeatures() const { return 0; }
274 
275     /// set OpenType features (bitmap)
setFeatures(int features)276     virtual void setFeatures( int features ) { }
277 
278     /// get kerning mode: true==ON, false=OFF
getKerning()279     virtual bool getKerning() const { return false; }
280 
281     /// set kerning mode: true==ON, false=OFF
setKerning(bool)282     virtual void setKerning(bool) {}
283 
284     /// sets current shaping mode
setShapingMode(shaping_mode_t)285     virtual void setShapingMode( shaping_mode_t /*mode*/ ) { }
286 
287     /// returns current shaping mode
getShapingMode()288     virtual shaping_mode_t getShapingMode() const { return SHAPING_MODE_FREETYPE; }
289 
290     /// sets current hinting mode
setHintingMode(hinting_mode_t)291     virtual void setHintingMode(hinting_mode_t /*mode*/) {}
292 
293     /// returns current hinting mode
getHintingMode()294     virtual hinting_mode_t getHintingMode() const { return HINTING_MODE_AUTOHINT; }
295 
296     /// clear cache
clearCache()297     virtual void clearCache() { }
298 
299     /// returns true if font is empty
300     virtual bool IsNull() const = 0;
301 
302     virtual bool operator!() const = 0;
303 
304     virtual void Clear() = 0;
305 
~LVFont()306     virtual ~LVFont() {}
307 
kerningEnabled()308     virtual bool kerningEnabled() { return false; }
309 
getKerningOffset(lChar32 ch1,lChar32 ch2,lChar32 def_char)310     virtual int getKerningOffset(lChar32 ch1, lChar32 ch2, lChar32 def_char) {
311         CR_UNUSED3(ch1, ch2, def_char);
312         return 0;
313     }
314 
checkFontLangCompat(const lString8 & langCode)315     virtual bool checkFontLangCompat(const lString8 &langCode) { return true; }
316 
317     /// set fallback font for this font
setFallbackFont(LVFontRef font)318     virtual void setFallbackFont(LVFontRef font) { CR_UNUSED(font); }
319 
320     /** \brief get fallback font for this font
321      * \param bitmask of processed fallback fonts
322      */
getFallbackFont(lUInt32 fallbackPassMask)323     virtual LVFont *getFallbackFont(lUInt32 fallbackPassMask) {
324         CR_UNUSED(fallbackPassMask)
325         return NULL;
326     }
327 
getFallbackMask()328     virtual lUInt32 getFallbackMask() const { return 0; }
setFallbackMask(lUInt32 mask)329     virtual void setFallbackMask(lUInt32 mask) { CR_UNUSED(mask) }
330 };
331 
332 /// to compare two fonts
333 bool operator==(const LVFont &r1, const LVFont &r2);
334 
335 #endif //__LV_FONT_H_INCLUDED__
336