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