Bug 1856663 - Add more chunks for Android mochitest-plain. r=jmaher,taskgraph-reviewe...
[gecko.git] / gfx / thebes / gfxSVGGlyphs.h
blobf17d887bce46e8ff1c2f428635b2ef132e26bf4f
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/. */
5 #ifndef GFX_SVG_GLYPHS_WRAPPER_H
6 #define GFX_SVG_GLYPHS_WRAPPER_H
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 "nsRefreshObservers.h"
19 class nsIContentViewer;
20 class gfxSVGGlyphs;
22 namespace mozilla {
23 class PresShell;
24 class SVGContextPaint;
25 namespace dom {
26 class Document;
27 class Element;
28 } // namespace dom
29 } // namespace mozilla
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
39 class gfxSVGGlyphsDocument final : public nsAPostRefreshObserver {
40 typedef mozilla::dom::Element Element;
42 public:
43 gfxSVGGlyphsDocument(const uint8_t* aBuffer, uint32_t aBufLen,
44 gfxSVGGlyphs* aSVGGlyphs);
46 Element* GetGlyphElement(uint32_t aGlyphId);
48 ~gfxSVGGlyphsDocument();
50 void DidRefresh() override;
52 size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
54 private:
55 nsresult ParseDocument(const uint8_t* aBuffer, uint32_t aBufLen);
57 nsresult SetupPresentation();
59 void FindGlyphElements(Element* aElement);
61 void InsertGlyphId(Element* aGlyphElement);
63 // Weak so as not to create a cycle. mOwner owns us so this can't dangle.
64 gfxSVGGlyphs* mOwner;
65 RefPtr<mozilla::dom::Document> mDocument;
66 nsCOMPtr<nsIContentViewer> mViewer;
67 RefPtr<mozilla::PresShell> mPresShell;
69 nsBaseHashtable<nsUint32HashKey, Element*, Element*> mGlyphIdMap;
72 /**
73 * Used by |gfxFontEntry| to represent the SVG table of an OpenType font.
74 * Handles lazy parsing of the SVG documents in the table, looking up SVG glyphs
75 * and rendering SVG glyphs.
76 * Each |gfxFontEntry| owns at most one |gfxSVGGlyphs| instance.
78 class gfxSVGGlyphs {
79 private:
80 typedef mozilla::dom::Element Element;
82 public:
83 /**
84 * @param aSVGTable The SVG table from the OpenType font
86 * The gfxSVGGlyphs object takes over ownership of the blob references
87 * that are passed in, and will hb_blob_destroy() them when finished;
88 * the caller should -not- destroy these references.
90 gfxSVGGlyphs(hb_blob_t* aSVGTable, gfxFontEntry* aFontEntry);
92 /**
93 * Releases our references to the SVG table and cleans up everything else.
95 ~gfxSVGGlyphs();
97 /**
98 * This is called when the refresh driver has ticked.
100 void DidRefresh();
103 * Find the |gfxSVGGlyphsDocument| containing an SVG glyph for |aGlyphId|.
104 * If |aGlyphId| does not map to an SVG document, return null.
105 * If a |gfxSVGGlyphsDocument| has not been created for the document, create
106 * one.
108 gfxSVGGlyphsDocument* FindOrCreateGlyphsDocument(uint32_t aGlyphId);
111 * Return true iff there is an SVG glyph for |aGlyphId|
113 bool HasSVGGlyph(uint32_t aGlyphId);
116 * Render the SVG glyph for |aGlyphId|
117 * @param aContextPaint Information on text context paints.
118 * See |SVGContextPaint|.
120 void RenderGlyph(gfxContext* aContext, uint32_t aGlyphId,
121 mozilla::SVGContextPaint* aContextPaint);
124 * Get the extents for the SVG glyph associated with |aGlyphId|
125 * @param aSVGToAppSpace The matrix mapping the SVG glyph space to the
126 * target context space
128 bool GetGlyphExtents(uint32_t aGlyphId, const gfxMatrix& aSVGToAppSpace,
129 gfxRect* aResult);
131 size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
133 gfxFontEntry* FontEntry() const { return mFontEntry; }
135 private:
136 Element* GetGlyphElement(uint32_t aGlyphId);
138 nsClassHashtable<nsUint32HashKey, gfxSVGGlyphsDocument> mGlyphDocs;
139 nsBaseHashtable<nsUint32HashKey, Element*, Element*> mGlyphIdMap;
141 hb_blob_t* mSVGData;
143 // pointer to the font entry that owns this gfxSVGGlyphs object
144 gfxFontEntry* MOZ_NON_OWNING_REF mFontEntry;
146 const struct Header {
147 mozilla::AutoSwap_PRUint16 mVersion;
148 mozilla::AutoSwap_PRUint32 mDocIndexOffset;
149 mozilla::AutoSwap_PRUint32 mColorPalettesOffset;
150 }* mHeader;
152 struct IndexEntry {
153 mozilla::AutoSwap_PRUint16 mStartGlyph;
154 mozilla::AutoSwap_PRUint16 mEndGlyph;
155 mozilla::AutoSwap_PRUint32 mDocOffset;
156 mozilla::AutoSwap_PRUint32 mDocLength;
159 const struct DocIndex {
160 mozilla::AutoSwap_PRUint16 mNumEntries;
161 IndexEntry mEntries[1]; /* actual length = mNumEntries */
162 }* mDocIndex;
164 static int CompareIndexEntries(const void* _a, const void* _b);
168 * XXX This is a complete hack and should die (see bug 1291494).
170 * This class is used when code fails to pass through an SVGContextPaint from
171 * the context in which we are painting. In that case we create one of these
172 * as a fallback and have it wrap the gfxContext's current gfxPattern and
173 * pretend that that is the paint context's fill pattern. In some contexts
174 * that will be the case, in others it will not. As we convert more code to
175 * Moz2D the less likely it is that this hack will work. It will also make
176 * converting to Moz2D harder.
178 class SimpleTextContextPaint : public mozilla::SVGContextPaint {
179 private:
180 static const mozilla::gfx::DeviceColor sZero;
182 static gfxMatrix SetupDeviceToPatternMatrix(gfxPattern* aPattern,
183 const gfxMatrix& aCTM) {
184 if (!aPattern) {
185 return gfxMatrix();
187 gfxMatrix deviceToUser = aCTM;
188 if (!deviceToUser.Invert()) {
189 return gfxMatrix(0, 0, 0, 0, 0, 0); // singular
191 return deviceToUser * aPattern->GetMatrix();
194 public:
195 SimpleTextContextPaint(gfxPattern* aFillPattern, gfxPattern* aStrokePattern,
196 const gfxMatrix& aCTM)
197 : mFillPattern(aFillPattern ? aFillPattern : new gfxPattern(sZero)),
198 mStrokePattern(aStrokePattern ? aStrokePattern
199 : new gfxPattern(sZero)) {
200 mFillMatrix = SetupDeviceToPatternMatrix(aFillPattern, aCTM);
201 mStrokeMatrix = SetupDeviceToPatternMatrix(aStrokePattern, aCTM);
204 already_AddRefed<gfxPattern> GetFillPattern(
205 const DrawTarget* aDrawTarget, float aOpacity, const gfxMatrix& aCTM,
206 imgDrawingParams& aImgParams) override {
207 if (mFillPattern) {
208 mFillPattern->SetMatrix(aCTM * mFillMatrix);
210 RefPtr<gfxPattern> fillPattern = mFillPattern;
211 return fillPattern.forget();
214 already_AddRefed<gfxPattern> GetStrokePattern(
215 const DrawTarget* aDrawTarget, float aOpacity, const gfxMatrix& aCTM,
216 imgDrawingParams& aImgParams) override {
217 if (mStrokePattern) {
218 mStrokePattern->SetMatrix(aCTM * mStrokeMatrix);
220 RefPtr<gfxPattern> strokePattern = mStrokePattern;
221 return strokePattern.forget();
224 float GetFillOpacity() const override { return mFillPattern ? 1.0f : 0.0f; }
226 float GetStrokeOpacity() const override {
227 return mStrokePattern ? 1.0f : 0.0f;
230 private:
231 RefPtr<gfxPattern> mFillPattern;
232 RefPtr<gfxPattern> mStrokePattern;
234 // Device space to pattern space transforms
235 gfxMatrix mFillMatrix;
236 gfxMatrix mStrokeMatrix;
239 #endif