1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2  * This Source Code Form is subject to the terms of the Mozilla Public
3  * License, v. 2.0. If a copy of the MPL was not distributed with this
4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 
6 #ifndef GFX_HARFBUZZSHAPER_H
7 #define GFX_HARFBUZZSHAPER_H
8 
9 #include "gfxFont.h"
10 
11 #include "harfbuzz/hb.h"
12 #include "nsUnicodeProperties.h"
13 #include "mozilla/gfx/2D.h"
14 
15 class gfxHarfBuzzShaper : public gfxFontShaper {
16 public:
17     explicit gfxHarfBuzzShaper(gfxFont *aFont);
18     virtual ~gfxHarfBuzzShaper();
19 
20     /*
21      * For HarfBuzz font callback functions, font_data is a ptr to a
22      * FontCallbackData struct
23      */
24     struct FontCallbackData {
25         gfxHarfBuzzShaper* mShaper;
26         mozilla::gfx::DrawTarget* mDrawTarget;
27     };
28 
29     bool Initialize();
30     virtual bool ShapeText(DrawTarget      *aDrawTarget,
31                            const char16_t *aText,
32                            uint32_t         aOffset,
33                            uint32_t         aLength,
34                            Script           aScript,
35                            bool             aVertical,
36                            gfxShapedText   *aShapedText);
37 
38     // get a given font table in harfbuzz blob form
39     hb_blob_t * GetFontTable(hb_tag_t aTag) const;
40 
41     // map unicode character to glyph ID
42     hb_codepoint_t GetNominalGlyph(hb_codepoint_t unicode) const;
43     hb_codepoint_t GetVariationGlyph(hb_codepoint_t unicode,
44                                      hb_codepoint_t variation_selector) const;
45 
46     // get harfbuzz glyph advance, in font design units
47     hb_position_t GetGlyphHAdvance(hb_codepoint_t glyph) const;
48 
49     hb_position_t GetGlyphVAdvance(hb_codepoint_t glyph) const;
50 
51     void GetGlyphVOrigin(hb_codepoint_t aGlyph,
52                          hb_position_t *aX, hb_position_t *aY) const;
53 
54     // get harfbuzz horizontal advance in 16.16 fixed point format.
55     static hb_position_t
56     HBGetGlyphHAdvance(hb_font_t *font, void *font_data,
57                        hb_codepoint_t glyph, void *user_data);
58 
59     // get harfbuzz vertical advance in 16.16 fixed point format.
60     static hb_position_t
61     HBGetGlyphVAdvance(hb_font_t *font, void *font_data,
62                        hb_codepoint_t glyph, void *user_data);
63 
64     static hb_bool_t
65     HBGetGlyphVOrigin(hb_font_t *font, void *font_data,
66                       hb_codepoint_t glyph,
67                       hb_position_t *x, hb_position_t *y,
68                       void *user_data);
69 
70     hb_position_t GetHKerning(uint16_t aFirstGlyph,
71                               uint16_t aSecondGlyph) const;
72 
73     hb_bool_t GetGlyphExtents(hb_codepoint_t aGlyph,
74                               hb_glyph_extents_t *aExtents) const;
75 
UseVerticalPresentationForms()76     bool UseVerticalPresentationForms() const
77     {
78         return mUseVerticalPresentationForms;
79     }
80 
81     static hb_script_t
GetHBScriptUsedForShaping(Script aScript)82     GetHBScriptUsedForShaping(Script aScript) {
83         // Decide what harfbuzz script code will be used for shaping
84         hb_script_t hbScript;
85         if (aScript <= Script::INHERITED) {
86             // For unresolved "common" or "inherited" runs,
87             // default to Latin for now.
88             hbScript = HB_SCRIPT_LATIN;
89         } else {
90             hbScript =
91                 hb_script_t(mozilla::unicode::GetScriptTagForCode(aScript));
92         }
93         return hbScript;
94     }
95 
96 protected:
97     nsresult SetGlyphsFromRun(DrawTarget     *aDrawTarget,
98                               gfxShapedText  *aShapedText,
99                               uint32_t        aOffset,
100                               uint32_t        aLength,
101                               const char16_t *aText,
102                               hb_buffer_t    *aBuffer,
103                               bool            aVertical);
104 
105     // retrieve glyph positions, applying advance adjustments and attachments
106     // returns results in appUnits
107     nscoord GetGlyphPositions(gfxContext *aContext,
108                               hb_buffer_t *aBuffer,
109                               nsTArray<nsPoint>& aPositions,
110                               uint32_t aAppUnitsPerDevUnit);
111 
112     bool InitializeVertical();
113     bool LoadHmtxTable();
114 
115     struct Glyf { // we only need the bounding-box at the beginning
116                   // of the glyph record, not the actual outline data
117         AutoSwap_PRInt16 numberOfContours;
118         AutoSwap_PRInt16 xMin;
119         AutoSwap_PRInt16 yMin;
120         AutoSwap_PRInt16 xMax;
121         AutoSwap_PRInt16 yMax;
122     };
123 
124     const Glyf *FindGlyf(hb_codepoint_t aGlyph, bool *aEmptyGlyf) const;
125 
126     // harfbuzz face object: we acquire a reference from the font entry
127     // on shaper creation, and release it in our destructor
128     hb_face_t         *mHBFace;
129 
130     // size-specific font object, owned by the gfxHarfBuzzShaper
131     hb_font_t         *mHBFont;
132 
133     FontCallbackData   mCallbackData;
134 
135     // Following table references etc are declared "mutable" because the
136     // harfbuzz callback functions take a const ptr to the shaper, but
137     // wish to cache tables here to avoid repeatedly looking them up
138     // in the font.
139 
140     // Old-style TrueType kern table, if we're not doing GPOS kerning
141     mutable hb_blob_t *mKernTable;
142 
143     // Cached copy of the hmtx table.
144     mutable hb_blob_t *mHmtxTable;
145 
146     // For vertical fonts, cached vmtx and VORG table, if present.
147     mutable hb_blob_t *mVmtxTable;
148     mutable hb_blob_t *mVORGTable;
149     // And for vertical TrueType (not CFF) fonts that have vmtx,
150     // we also use loca and glyf to get glyph bounding boxes.
151     mutable hb_blob_t *mLocaTable;
152     mutable hb_blob_t *mGlyfTable;
153 
154     // Cached pointer to cmap subtable to be used for char-to-glyph mapping.
155     // This comes from GetFontTablePtr; if it is non-null, our destructor
156     // must call ReleaseFontTablePtr to avoid permanently caching the table.
157     mutable hb_blob_t *mCmapTable;
158     mutable int32_t    mCmapFormat;
159     mutable uint32_t   mSubtableOffset;
160     mutable uint32_t   mUVSTableOffset;
161 
162     // Cached copy of numLongMetrics field from the hhea table,
163     // for use when looking up glyph metrics; initialized to 0 by the
164     // constructor so we can tell it hasn't been set yet.
165     // This is a signed value so that we can use -1 to indicate
166     // an error (if the hhea table was not available).
167     mutable int32_t    mNumLongHMetrics;
168     // Similarly for vhea if it's a vertical font.
169     mutable int32_t    mNumLongVMetrics;
170 
171     // Whether the font implements GetGlyph, or we should read tables
172     // directly
173     bool mUseFontGetGlyph;
174     // Whether the font implements GetGlyphWidth, or we should read tables
175     // directly to get ideal widths
176     bool mUseFontGlyphWidths;
177 
178     bool mInitialized;
179     bool mVerticalInitialized;
180 
181     // Whether to use vertical presentation forms for CJK characters
182     // when available (only set if the 'vert' feature is not available).
183     bool mUseVerticalPresentationForms;
184 
185     // these are set from the FindGlyf callback on first use of the glyf data
186     mutable bool mLoadedLocaGlyf;
187     mutable bool mLocaLongOffsets;
188 };
189 
190 #endif /* GFX_HARFBUZZSHAPER_H */
191