summaryrefslogtreecommitdiffstats
path: root/gfx/thebes/gfxSVGGlyphs.h
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/thebes/gfxSVGGlyphs.h')
-rw-r--r--gfx/thebes/gfxSVGGlyphs.h242
1 files changed, 242 insertions, 0 deletions
diff --git a/gfx/thebes/gfxSVGGlyphs.h b/gfx/thebes/gfxSVGGlyphs.h
new file mode 100644
index 000000000..8ebebb44b
--- /dev/null
+++ b/gfx/thebes/gfxSVGGlyphs.h
@@ -0,0 +1,242 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef GFX_SVG_GLYPHS_WRAPPER_H
+#define GFX_SVG_GLYPHS_WRAPPER_H
+
+#include "gfxFontUtils.h"
+#include "mozilla/gfx/2D.h"
+#include "nsString.h"
+#include "nsClassHashtable.h"
+#include "nsBaseHashtable.h"
+#include "nsHashKeys.h"
+#include "gfxPattern.h"
+#include "mozilla/gfx/UserData.h"
+#include "mozilla/SVGContextPaint.h"
+#include "nsRefreshDriver.h"
+
+class nsIDocument;
+class nsIContentViewer;
+class nsIPresShell;
+class gfxSVGGlyphs;
+
+namespace mozilla {
+class SVGContextPaint;
+namespace dom {
+class Element;
+} // namespace dom
+} // namespace mozilla
+
+/**
+ * Wraps an SVG document contained in the SVG table of an OpenType font.
+ * There may be multiple SVG documents in an SVG table which we lazily parse
+ * so we have an instance of this class for every document in the SVG table
+ * which contains a glyph ID which has been used
+ * Finds and looks up elements contained in the SVG document which have glyph
+ * mappings to be drawn by gfxSVGGlyphs
+ */
+class gfxSVGGlyphsDocument final : public nsAPostRefreshObserver
+{
+ typedef mozilla::dom::Element Element;
+
+public:
+ gfxSVGGlyphsDocument(const uint8_t *aBuffer, uint32_t aBufLen,
+ gfxSVGGlyphs *aSVGGlyphs);
+
+ Element *GetGlyphElement(uint32_t aGlyphId);
+
+ ~gfxSVGGlyphsDocument();
+
+ virtual void DidRefresh() override;
+
+ size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
+
+private:
+ nsresult ParseDocument(const uint8_t *aBuffer, uint32_t aBufLen);
+
+ nsresult SetupPresentation();
+
+ void FindGlyphElements(Element *aElement);
+
+ void InsertGlyphId(Element *aGlyphElement);
+
+ // Weak so as not to create a cycle. mOwner owns us so this can't dangle.
+ gfxSVGGlyphs* mOwner;
+ nsCOMPtr<nsIDocument> mDocument;
+ nsCOMPtr<nsIContentViewer> mViewer;
+ nsCOMPtr<nsIPresShell> mPresShell;
+
+ nsBaseHashtable<nsUint32HashKey, Element*, Element*> mGlyphIdMap;
+
+ nsCString mSVGGlyphsDocumentURI;
+};
+
+/**
+ * Used by |gfxFontEntry| to represent the SVG table of an OpenType font.
+ * Handles lazy parsing of the SVG documents in the table, looking up SVG glyphs
+ * and rendering SVG glyphs.
+ * Each |gfxFontEntry| owns at most one |gfxSVGGlyphs| instance.
+ */
+class gfxSVGGlyphs
+{
+private:
+ typedef mozilla::dom::Element Element;
+
+public:
+ /**
+ * @param aSVGTable The SVG table from the OpenType font
+ *
+ * The gfxSVGGlyphs object takes over ownership of the blob references
+ * that are passed in, and will hb_blob_destroy() them when finished;
+ * the caller should -not- destroy these references.
+ */
+ gfxSVGGlyphs(hb_blob_t *aSVGTable, gfxFontEntry *aFontEntry);
+
+ /**
+ * Releases our references to the SVG table and cleans up everything else.
+ */
+ ~gfxSVGGlyphs();
+
+ /**
+ * This is called when the refresh driver has ticked.
+ */
+ void DidRefresh();
+
+ /**
+ * Find the |gfxSVGGlyphsDocument| containing an SVG glyph for |aGlyphId|.
+ * If |aGlyphId| does not map to an SVG document, return null.
+ * If a |gfxSVGGlyphsDocument| has not been created for the document, create one.
+ */
+ gfxSVGGlyphsDocument *FindOrCreateGlyphsDocument(uint32_t aGlyphId);
+
+ /**
+ * Return true iff there is an SVG glyph for |aGlyphId|
+ */
+ bool HasSVGGlyph(uint32_t aGlyphId);
+
+ /**
+ * Render the SVG glyph for |aGlyphId|
+ * @param aContextPaint Information on text context paints.
+ * See |SVGContextPaint|.
+ */
+ bool RenderGlyph(gfxContext *aContext, uint32_t aGlyphId,
+ mozilla::SVGContextPaint* aContextPaint);
+
+ /**
+ * Get the extents for the SVG glyph associated with |aGlyphId|
+ * @param aSVGToAppSpace The matrix mapping the SVG glyph space to the
+ * target context space
+ */
+ bool GetGlyphExtents(uint32_t aGlyphId, const gfxMatrix& aSVGToAppSpace,
+ gfxRect *aResult);
+
+ size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
+
+private:
+ Element *GetGlyphElement(uint32_t aGlyphId);
+
+ nsClassHashtable<nsUint32HashKey, gfxSVGGlyphsDocument> mGlyphDocs;
+ nsBaseHashtable<nsUint32HashKey, Element*, Element*> mGlyphIdMap;
+
+ hb_blob_t *mSVGData;
+ gfxFontEntry *mFontEntry;
+
+ const struct Header {
+ mozilla::AutoSwap_PRUint16 mVersion;
+ mozilla::AutoSwap_PRUint32 mDocIndexOffset;
+ mozilla::AutoSwap_PRUint32 mColorPalettesOffset;
+ } *mHeader;
+
+ struct IndexEntry {
+ mozilla::AutoSwap_PRUint16 mStartGlyph;
+ mozilla::AutoSwap_PRUint16 mEndGlyph;
+ mozilla::AutoSwap_PRUint32 mDocOffset;
+ mozilla::AutoSwap_PRUint32 mDocLength;
+ };
+
+ const struct DocIndex {
+ mozilla::AutoSwap_PRUint16 mNumEntries;
+ IndexEntry mEntries[1]; /* actual length = mNumEntries */
+ } *mDocIndex;
+
+ static int CompareIndexEntries(const void *_a, const void *_b);
+};
+
+/**
+ * XXX This is a complete hack and should die (see bug 1291494).
+ *
+ * This class is used when code fails to pass through an SVGContextPaint from
+ * the context in which we are painting. In that case we create one of these
+ * as a fallback and have it wrap the gfxContext's current gfxPattern and
+ * pretend that that is the paint context's fill pattern. In some contexts
+ * that will be the case, in others it will not. As we convert more code to
+ * Moz2D the less likely it is that this hack will work. It will also make
+ * converting to Moz2D harder.
+ */
+class SimpleTextContextPaint : public mozilla::SVGContextPaint
+{
+private:
+ static const mozilla::gfx::Color sZero;
+
+ static gfxMatrix SetupDeviceToPatternMatrix(gfxPattern *aPattern,
+ const gfxMatrix& aCTM)
+ {
+ if (!aPattern) {
+ return gfxMatrix();
+ }
+ gfxMatrix deviceToUser = aCTM;
+ if (!deviceToUser.Invert()) {
+ return gfxMatrix(0, 0, 0, 0, 0, 0); // singular
+ }
+ return deviceToUser * aPattern->GetMatrix();
+ }
+
+public:
+ SimpleTextContextPaint(gfxPattern *aFillPattern, gfxPattern *aStrokePattern,
+ const gfxMatrix& aCTM) :
+ mFillPattern(aFillPattern ? aFillPattern : new gfxPattern(sZero)),
+ mStrokePattern(aStrokePattern ? aStrokePattern : new gfxPattern(sZero))
+ {
+ mFillMatrix = SetupDeviceToPatternMatrix(aFillPattern, aCTM);
+ mStrokeMatrix = SetupDeviceToPatternMatrix(aStrokePattern, aCTM);
+ }
+
+ already_AddRefed<gfxPattern> GetFillPattern(const DrawTarget* aDrawTarget,
+ float aOpacity,
+ const gfxMatrix& aCTM) {
+ if (mFillPattern) {
+ mFillPattern->SetMatrix(aCTM * mFillMatrix);
+ }
+ RefPtr<gfxPattern> fillPattern = mFillPattern;
+ return fillPattern.forget();
+ }
+
+ already_AddRefed<gfxPattern> GetStrokePattern(const DrawTarget* aDrawTarget,
+ float aOpacity,
+ const gfxMatrix& aCTM) {
+ if (mStrokePattern) {
+ mStrokePattern->SetMatrix(aCTM * mStrokeMatrix);
+ }
+ RefPtr<gfxPattern> strokePattern = mStrokePattern;
+ return strokePattern.forget();
+ }
+
+ float GetFillOpacity() const {
+ return mFillPattern ? 1.0f : 0.0f;
+ }
+
+ float GetStrokeOpacity() const {
+ return mStrokePattern ? 1.0f : 0.0f;
+ }
+
+private:
+ RefPtr<gfxPattern> mFillPattern;
+ RefPtr<gfxPattern> mStrokePattern;
+
+ // Device space to pattern space transforms
+ gfxMatrix mFillMatrix;
+ gfxMatrix mStrokeMatrix;
+};
+
+#endif