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"
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
;
24 class SVGContextPaint
;
29 } // namespace mozilla
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
;
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;
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.
65 RefPtr
<mozilla::dom::Document
> mDocument
;
66 nsCOMPtr
<nsIContentViewer
> mViewer
;
67 RefPtr
<mozilla::PresShell
> mPresShell
;
69 nsBaseHashtable
<nsUint32HashKey
, Element
*, Element
*> mGlyphIdMap
;
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.
80 typedef mozilla::dom::Element Element
;
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
);
93 * Releases our references to the SVG table and cleans up everything else.
98 * This is called when the refresh driver has ticked.
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
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
,
131 size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf
) const;
133 gfxFontEntry
* FontEntry() const { return mFontEntry
; }
136 Element
* GetGlyphElement(uint32_t aGlyphId
);
138 nsClassHashtable
<nsUint32HashKey
, gfxSVGGlyphsDocument
> mGlyphDocs
;
139 nsBaseHashtable
<nsUint32HashKey
, Element
*, Element
*> mGlyphIdMap
;
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
;
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 */
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
{
180 static const mozilla::gfx::DeviceColor sZero
;
182 static gfxMatrix
SetupDeviceToPatternMatrix(gfxPattern
* aPattern
,
183 const gfxMatrix
& aCTM
) {
187 gfxMatrix deviceToUser
= aCTM
;
188 if (!deviceToUser
.Invert()) {
189 return gfxMatrix(0, 0, 0, 0, 0, 0); // singular
191 return deviceToUser
* aPattern
->GetMatrix();
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
{
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
;
231 RefPtr
<gfxPattern
> mFillPattern
;
232 RefPtr
<gfxPattern
> mStrokePattern
;
234 // Device space to pattern space transforms
235 gfxMatrix mFillMatrix
;
236 gfxMatrix mStrokeMatrix
;