/src/mozilla-central/gfx/thebes/gfxSVGGlyphs.h
Line | Count | Source (jump to first uncovered line) |
1 | | /* This Source Code Form is subject to the terms of the Mozilla Public |
2 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
3 | | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
4 | | |
5 | | #ifndef GFX_SVG_GLYPHS_WRAPPER_H |
6 | | #define GFX_SVG_GLYPHS_WRAPPER_H |
7 | | |
8 | | #include "gfxFontUtils.h" |
9 | | #include "mozilla/gfx/2D.h" |
10 | | #include "nsString.h" |
11 | | #include "nsClassHashtable.h" |
12 | | #include "nsBaseHashtable.h" |
13 | | #include "nsHashKeys.h" |
14 | | #include "gfxPattern.h" |
15 | | #include "mozilla/gfx/UserData.h" |
16 | | #include "mozilla/SVGContextPaint.h" |
17 | | #include "nsRefreshDriver.h" |
18 | | |
19 | | class nsIDocument; |
20 | | class nsIContentViewer; |
21 | | class nsIPresShell; |
22 | | class gfxSVGGlyphs; |
23 | | |
24 | | namespace mozilla { |
25 | | class SVGContextPaint; |
26 | | namespace dom { |
27 | | class Element; |
28 | | } // namespace dom |
29 | | } // namespace mozilla |
30 | | |
31 | | /** |
32 | | * Wraps an SVG document contained in the SVG table of an OpenType font. |
33 | | * There may be multiple SVG documents in an SVG table which we lazily parse |
34 | | * so we have an instance of this class for every document in the SVG table |
35 | | * which contains a glyph ID which has been used |
36 | | * Finds and looks up elements contained in the SVG document which have glyph |
37 | | * mappings to be drawn by gfxSVGGlyphs |
38 | | */ |
39 | | class gfxSVGGlyphsDocument final : public nsAPostRefreshObserver |
40 | | { |
41 | | typedef mozilla::dom::Element Element; |
42 | | |
43 | | public: |
44 | | gfxSVGGlyphsDocument(const uint8_t *aBuffer, uint32_t aBufLen, |
45 | | gfxSVGGlyphs *aSVGGlyphs); |
46 | | |
47 | | Element *GetGlyphElement(uint32_t aGlyphId); |
48 | | |
49 | | ~gfxSVGGlyphsDocument(); |
50 | | |
51 | | virtual void DidRefresh() override; |
52 | | |
53 | | size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const; |
54 | | |
55 | | private: |
56 | | nsresult ParseDocument(const uint8_t *aBuffer, uint32_t aBufLen); |
57 | | |
58 | | nsresult SetupPresentation(); |
59 | | |
60 | | void FindGlyphElements(Element *aElement); |
61 | | |
62 | | void InsertGlyphId(Element *aGlyphElement); |
63 | | |
64 | | // Weak so as not to create a cycle. mOwner owns us so this can't dangle. |
65 | | gfxSVGGlyphs* mOwner; |
66 | | nsCOMPtr<nsIDocument> mDocument; |
67 | | nsCOMPtr<nsIContentViewer> mViewer; |
68 | | nsCOMPtr<nsIPresShell> mPresShell; |
69 | | |
70 | | nsBaseHashtable<nsUint32HashKey, Element*, Element*> mGlyphIdMap; |
71 | | |
72 | | nsCString mSVGGlyphsDocumentURI; |
73 | | }; |
74 | | |
75 | | /** |
76 | | * Used by |gfxFontEntry| to represent the SVG table of an OpenType font. |
77 | | * Handles lazy parsing of the SVG documents in the table, looking up SVG glyphs |
78 | | * and rendering SVG glyphs. |
79 | | * Each |gfxFontEntry| owns at most one |gfxSVGGlyphs| instance. |
80 | | */ |
81 | | class gfxSVGGlyphs |
82 | | { |
83 | | private: |
84 | | typedef mozilla::dom::Element Element; |
85 | | |
86 | | public: |
87 | | /** |
88 | | * @param aSVGTable The SVG table from the OpenType font |
89 | | * |
90 | | * The gfxSVGGlyphs object takes over ownership of the blob references |
91 | | * that are passed in, and will hb_blob_destroy() them when finished; |
92 | | * the caller should -not- destroy these references. |
93 | | */ |
94 | | gfxSVGGlyphs(hb_blob_t *aSVGTable, gfxFontEntry *aFontEntry); |
95 | | |
96 | | /** |
97 | | * Releases our references to the SVG table and cleans up everything else. |
98 | | */ |
99 | | ~gfxSVGGlyphs(); |
100 | | |
101 | | /** |
102 | | * This is called when the refresh driver has ticked. |
103 | | */ |
104 | | void DidRefresh(); |
105 | | |
106 | | /** |
107 | | * Find the |gfxSVGGlyphsDocument| containing an SVG glyph for |aGlyphId|. |
108 | | * If |aGlyphId| does not map to an SVG document, return null. |
109 | | * If a |gfxSVGGlyphsDocument| has not been created for the document, create one. |
110 | | */ |
111 | | gfxSVGGlyphsDocument *FindOrCreateGlyphsDocument(uint32_t aGlyphId); |
112 | | |
113 | | /** |
114 | | * Return true iff there is an SVG glyph for |aGlyphId| |
115 | | */ |
116 | | bool HasSVGGlyph(uint32_t aGlyphId); |
117 | | |
118 | | /** |
119 | | * Render the SVG glyph for |aGlyphId| |
120 | | * @param aContextPaint Information on text context paints. |
121 | | * See |SVGContextPaint|. |
122 | | */ |
123 | | void RenderGlyph(gfxContext *aContext, uint32_t aGlyphId, |
124 | | mozilla::SVGContextPaint* aContextPaint); |
125 | | |
126 | | /** |
127 | | * Get the extents for the SVG glyph associated with |aGlyphId| |
128 | | * @param aSVGToAppSpace The matrix mapping the SVG glyph space to the |
129 | | * target context space |
130 | | */ |
131 | | bool GetGlyphExtents(uint32_t aGlyphId, const gfxMatrix& aSVGToAppSpace, |
132 | | gfxRect *aResult); |
133 | | |
134 | | size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const; |
135 | | |
136 | | private: |
137 | | Element *GetGlyphElement(uint32_t aGlyphId); |
138 | | |
139 | | nsClassHashtable<nsUint32HashKey, gfxSVGGlyphsDocument> mGlyphDocs; |
140 | | nsBaseHashtable<nsUint32HashKey, Element*, Element*> mGlyphIdMap; |
141 | | |
142 | | hb_blob_t *mSVGData; |
143 | | |
144 | | // pointer to the font entry that owns this gfxSVGGlyphs object |
145 | | gfxFontEntry* MOZ_NON_OWNING_REF mFontEntry; |
146 | | |
147 | | const struct Header { |
148 | | mozilla::AutoSwap_PRUint16 mVersion; |
149 | | mozilla::AutoSwap_PRUint32 mDocIndexOffset; |
150 | | mozilla::AutoSwap_PRUint32 mColorPalettesOffset; |
151 | | } *mHeader; |
152 | | |
153 | | struct IndexEntry { |
154 | | mozilla::AutoSwap_PRUint16 mStartGlyph; |
155 | | mozilla::AutoSwap_PRUint16 mEndGlyph; |
156 | | mozilla::AutoSwap_PRUint32 mDocOffset; |
157 | | mozilla::AutoSwap_PRUint32 mDocLength; |
158 | | }; |
159 | | |
160 | | const struct DocIndex { |
161 | | mozilla::AutoSwap_PRUint16 mNumEntries; |
162 | | IndexEntry mEntries[1]; /* actual length = mNumEntries */ |
163 | | } *mDocIndex; |
164 | | |
165 | | static int CompareIndexEntries(const void *_a, const void *_b); |
166 | | }; |
167 | | |
168 | | /** |
169 | | * XXX This is a complete hack and should die (see bug 1291494). |
170 | | * |
171 | | * This class is used when code fails to pass through an SVGContextPaint from |
172 | | * the context in which we are painting. In that case we create one of these |
173 | | * as a fallback and have it wrap the gfxContext's current gfxPattern and |
174 | | * pretend that that is the paint context's fill pattern. In some contexts |
175 | | * that will be the case, in others it will not. As we convert more code to |
176 | | * Moz2D the less likely it is that this hack will work. It will also make |
177 | | * converting to Moz2D harder. |
178 | | */ |
179 | | class SimpleTextContextPaint : public mozilla::SVGContextPaint |
180 | | { |
181 | | private: |
182 | | static const mozilla::gfx::Color sZero; |
183 | | |
184 | | static gfxMatrix SetupDeviceToPatternMatrix(gfxPattern *aPattern, |
185 | | const gfxMatrix& aCTM) |
186 | 0 | { |
187 | 0 | if (!aPattern) { |
188 | 0 | return gfxMatrix(); |
189 | 0 | } |
190 | 0 | gfxMatrix deviceToUser = aCTM; |
191 | 0 | if (!deviceToUser.Invert()) { |
192 | 0 | return gfxMatrix(0, 0, 0, 0, 0, 0); // singular |
193 | 0 | } |
194 | 0 | return deviceToUser * aPattern->GetMatrix(); |
195 | 0 | } |
196 | | |
197 | | public: |
198 | | SimpleTextContextPaint(gfxPattern *aFillPattern, gfxPattern *aStrokePattern, |
199 | | const gfxMatrix& aCTM) : |
200 | | mFillPattern(aFillPattern ? aFillPattern : new gfxPattern(sZero)), |
201 | | mStrokePattern(aStrokePattern ? aStrokePattern : new gfxPattern(sZero)) |
202 | 0 | { |
203 | 0 | mFillMatrix = SetupDeviceToPatternMatrix(aFillPattern, aCTM); |
204 | 0 | mStrokeMatrix = SetupDeviceToPatternMatrix(aStrokePattern, aCTM); |
205 | 0 | } |
206 | | |
207 | | already_AddRefed<gfxPattern> |
208 | | GetFillPattern(const DrawTarget* aDrawTarget, |
209 | | float aOpacity, |
210 | | const gfxMatrix& aCTM, |
211 | 0 | imgDrawingParams& aImgParams) override { |
212 | 0 | if (mFillPattern) { |
213 | 0 | mFillPattern->SetMatrix(aCTM * mFillMatrix); |
214 | 0 | } |
215 | 0 | RefPtr<gfxPattern> fillPattern = mFillPattern; |
216 | 0 | return fillPattern.forget(); |
217 | 0 | } |
218 | | |
219 | | already_AddRefed<gfxPattern> |
220 | | GetStrokePattern(const DrawTarget* aDrawTarget, |
221 | | float aOpacity, |
222 | | const gfxMatrix& aCTM, |
223 | 0 | imgDrawingParams& aImgParams) override { |
224 | 0 | if (mStrokePattern) { |
225 | 0 | mStrokePattern->SetMatrix(aCTM * mStrokeMatrix); |
226 | 0 | } |
227 | 0 | RefPtr<gfxPattern> strokePattern = mStrokePattern; |
228 | 0 | return strokePattern.forget(); |
229 | 0 | } |
230 | | |
231 | 0 | float GetFillOpacity() const override { |
232 | 0 | return mFillPattern ? 1.0f : 0.0f; |
233 | 0 | } |
234 | | |
235 | 0 | float GetStrokeOpacity() const override { |
236 | 0 | return mStrokePattern ? 1.0f : 0.0f; |
237 | 0 | } |
238 | | |
239 | | private: |
240 | | RefPtr<gfxPattern> mFillPattern; |
241 | | RefPtr<gfxPattern> mStrokePattern; |
242 | | |
243 | | // Device space to pattern space transforms |
244 | | gfxMatrix mFillMatrix; |
245 | | gfxMatrix mStrokeMatrix; |
246 | | }; |
247 | | |
248 | | #endif |