Line data Source code
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 : gfxFontEntry *mFontEntry;
144 :
145 : const struct Header {
146 : mozilla::AutoSwap_PRUint16 mVersion;
147 : mozilla::AutoSwap_PRUint32 mDocIndexOffset;
148 : mozilla::AutoSwap_PRUint32 mColorPalettesOffset;
149 : } *mHeader;
150 :
151 : struct IndexEntry {
152 : mozilla::AutoSwap_PRUint16 mStartGlyph;
153 : mozilla::AutoSwap_PRUint16 mEndGlyph;
154 : mozilla::AutoSwap_PRUint32 mDocOffset;
155 : mozilla::AutoSwap_PRUint32 mDocLength;
156 : };
157 :
158 : const struct DocIndex {
159 : mozilla::AutoSwap_PRUint16 mNumEntries;
160 : IndexEntry mEntries[1]; /* actual length = mNumEntries */
161 : } *mDocIndex;
162 :
163 : static int CompareIndexEntries(const void *_a, const void *_b);
164 : };
165 :
166 : /**
167 : * XXX This is a complete hack and should die (see bug 1291494).
168 : *
169 : * This class is used when code fails to pass through an SVGContextPaint from
170 : * the context in which we are painting. In that case we create one of these
171 : * as a fallback and have it wrap the gfxContext's current gfxPattern and
172 : * pretend that that is the paint context's fill pattern. In some contexts
173 : * that will be the case, in others it will not. As we convert more code to
174 : * Moz2D the less likely it is that this hack will work. It will also make
175 : * converting to Moz2D harder.
176 : */
177 0 : class SimpleTextContextPaint : public mozilla::SVGContextPaint
178 : {
179 : private:
180 : static const mozilla::gfx::Color sZero;
181 :
182 0 : static gfxMatrix SetupDeviceToPatternMatrix(gfxPattern *aPattern,
183 : const gfxMatrix& aCTM)
184 : {
185 0 : if (!aPattern) {
186 0 : return gfxMatrix();
187 : }
188 0 : gfxMatrix deviceToUser = aCTM;
189 0 : if (!deviceToUser.Invert()) {
190 0 : return gfxMatrix(0, 0, 0, 0, 0, 0); // singular
191 : }
192 0 : return deviceToUser * aPattern->GetMatrix();
193 : }
194 :
195 : public:
196 0 : SimpleTextContextPaint(gfxPattern *aFillPattern, gfxPattern *aStrokePattern,
197 0 : const gfxMatrix& aCTM) :
198 0 : mFillPattern(aFillPattern ? aFillPattern : new gfxPattern(sZero)),
199 0 : mStrokePattern(aStrokePattern ? aStrokePattern : new gfxPattern(sZero))
200 : {
201 0 : mFillMatrix = SetupDeviceToPatternMatrix(aFillPattern, aCTM);
202 0 : mStrokeMatrix = SetupDeviceToPatternMatrix(aStrokePattern, aCTM);
203 0 : }
204 :
205 : already_AddRefed<gfxPattern>
206 0 : GetFillPattern(const DrawTarget* aDrawTarget,
207 : float aOpacity,
208 : const gfxMatrix& aCTM,
209 : imgDrawingParams& aImgParams) override {
210 0 : if (mFillPattern) {
211 0 : mFillPattern->SetMatrix(aCTM * mFillMatrix);
212 : }
213 0 : RefPtr<gfxPattern> fillPattern = mFillPattern;
214 0 : return fillPattern.forget();
215 : }
216 :
217 : already_AddRefed<gfxPattern>
218 0 : GetStrokePattern(const DrawTarget* aDrawTarget,
219 : float aOpacity,
220 : const gfxMatrix& aCTM,
221 : imgDrawingParams& aImgParams) override {
222 0 : if (mStrokePattern) {
223 0 : mStrokePattern->SetMatrix(aCTM * mStrokeMatrix);
224 : }
225 0 : RefPtr<gfxPattern> strokePattern = mStrokePattern;
226 0 : return strokePattern.forget();
227 : }
228 :
229 0 : float GetFillOpacity() const override {
230 0 : return mFillPattern ? 1.0f : 0.0f;
231 : }
232 :
233 0 : float GetStrokeOpacity() const override {
234 0 : return mStrokePattern ? 1.0f : 0.0f;
235 : }
236 :
237 : private:
238 : RefPtr<gfxPattern> mFillPattern;
239 : RefPtr<gfxPattern> mStrokePattern;
240 :
241 : // Device space to pattern space transforms
242 : gfxMatrix mFillMatrix;
243 : gfxMatrix mStrokeMatrix;
244 : };
245 :
246 : #endif
|