gfx/thebes/gfxSVGGlyphs.h

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/gfx/thebes/gfxSVGGlyphs.h	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,283 @@
     1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.7 +
     1.8 +#ifndef GFX_SVG_GLYPHS_WRAPPER_H
     1.9 +#define GFX_SVG_GLYPHS_WRAPPER_H
    1.10 +
    1.11 +#include "gfxFontUtils.h"
    1.12 +#include "nsString.h"
    1.13 +#include "nsAutoPtr.h"
    1.14 +#include "nsClassHashtable.h"
    1.15 +#include "nsBaseHashtable.h"
    1.16 +#include "nsHashKeys.h"
    1.17 +#include "gfxPattern.h"
    1.18 +#include "mozilla/gfx/UserData.h"
    1.19 +#include "nsRefreshDriver.h"
    1.20 +#include "DrawMode.h"
    1.21 +
    1.22 +class nsIDocument;
    1.23 +class nsIContentViewer;
    1.24 +class nsIPresShell;
    1.25 +class gfxSVGGlyphs;
    1.26 +class gfxTextContextPaint;
    1.27 +
    1.28 +namespace mozilla {
    1.29 +namespace dom {
    1.30 +class Element;
    1.31 +}
    1.32 +}
    1.33 +
    1.34 +/**
    1.35 + * Wraps an SVG document contained in the SVG table of an OpenType font.
    1.36 + * There may be multiple SVG documents in an SVG table which we lazily parse
    1.37 + *   so we have an instance of this class for every document in the SVG table
    1.38 + *   which contains a glyph ID which has been used
    1.39 + * Finds and looks up elements contained in the SVG document which have glyph
    1.40 + *   mappings to be drawn by gfxSVGGlyphs
    1.41 + */
    1.42 +class gfxSVGGlyphsDocument MOZ_FINAL : public nsAPostRefreshObserver
    1.43 +{
    1.44 +    typedef mozilla::dom::Element Element;
    1.45 +
    1.46 +public:
    1.47 +    gfxSVGGlyphsDocument(const uint8_t *aBuffer, uint32_t aBufLen,
    1.48 +                         gfxSVGGlyphs *aSVGGlyphs);
    1.49 +
    1.50 +    Element *GetGlyphElement(uint32_t aGlyphId);
    1.51 +
    1.52 +    ~gfxSVGGlyphsDocument();
    1.53 +
    1.54 +    virtual void DidRefresh() MOZ_OVERRIDE;
    1.55 +
    1.56 +private:
    1.57 +    nsresult ParseDocument(const uint8_t *aBuffer, uint32_t aBufLen);
    1.58 +
    1.59 +    nsresult SetupPresentation();
    1.60 +
    1.61 +    void FindGlyphElements(Element *aElement);
    1.62 +
    1.63 +    void InsertGlyphId(Element *aGlyphElement);
    1.64 +
    1.65 +    // Weak so as not to create a cycle. mOwner owns us so this can't dangle.
    1.66 +    gfxSVGGlyphs* mOwner;
    1.67 +    nsCOMPtr<nsIDocument> mDocument;
    1.68 +    nsCOMPtr<nsIContentViewer> mViewer;
    1.69 +    nsCOMPtr<nsIPresShell> mPresShell;
    1.70 +
    1.71 +    nsBaseHashtable<nsUint32HashKey, Element*, Element*> mGlyphIdMap;
    1.72 +
    1.73 +    nsAutoCString mSVGGlyphsDocumentURI;
    1.74 +};
    1.75 +
    1.76 +/**
    1.77 + * Used by |gfxFontEntry| to represent the SVG table of an OpenType font.
    1.78 + * Handles lazy parsing of the SVG documents in the table, looking up SVG glyphs
    1.79 + *   and rendering SVG glyphs.
    1.80 + * Each |gfxFontEntry| owns at most one |gfxSVGGlyphs| instance.
    1.81 + */
    1.82 +class gfxSVGGlyphs
    1.83 +{
    1.84 +private:
    1.85 +    typedef mozilla::dom::Element Element;
    1.86 +
    1.87 +public:
    1.88 +    /**
    1.89 +     * @param aSVGTable The SVG table from the OpenType font
    1.90 +     *
    1.91 +     * The gfxSVGGlyphs object takes over ownership of the blob references
    1.92 +     * that are passed in, and will hb_blob_destroy() them when finished;
    1.93 +     * the caller should -not- destroy these references.
    1.94 +     */
    1.95 +    gfxSVGGlyphs(hb_blob_t *aSVGTable, gfxFontEntry *aFontEntry);
    1.96 +
    1.97 +    /**
    1.98 +     * Releases our references to the SVG table and cleans up everything else.
    1.99 +     */
   1.100 +    ~gfxSVGGlyphs();
   1.101 +
   1.102 +    /**
   1.103 +     * This is called when the refresh driver has ticked.
   1.104 +     */
   1.105 +    void DidRefresh();
   1.106 +
   1.107 +    /**
   1.108 +     * Find the |gfxSVGGlyphsDocument| containing an SVG glyph for |aGlyphId|.
   1.109 +     * If |aGlyphId| does not map to an SVG document, return null.
   1.110 +     * If a |gfxSVGGlyphsDocument| has not been created for the document, create one.
   1.111 +     */
   1.112 +    gfxSVGGlyphsDocument *FindOrCreateGlyphsDocument(uint32_t aGlyphId);
   1.113 +
   1.114 +    /**
   1.115 +     * Return true iff there is an SVG glyph for |aGlyphId|
   1.116 +     */
   1.117 +    bool HasSVGGlyph(uint32_t aGlyphId);
   1.118 +
   1.119 +    /**
   1.120 +     * Render the SVG glyph for |aGlyphId|
   1.121 +     * @param aDrawMode Whether to fill or stroke or both; see DrawMode
   1.122 +     * @param aContextPaint Information on text context paints.
   1.123 +     *   See |gfxTextContextPaint|.
   1.124 +     */
   1.125 +    bool RenderGlyph(gfxContext *aContext, uint32_t aGlyphId, DrawMode aDrawMode,
   1.126 +                     gfxTextContextPaint *aContextPaint);
   1.127 +
   1.128 +    /**
   1.129 +     * Get the extents for the SVG glyph associated with |aGlyphId|
   1.130 +     * @param aSVGToAppSpace The matrix mapping the SVG glyph space to the
   1.131 +     *   target context space
   1.132 +     */
   1.133 +    bool GetGlyphExtents(uint32_t aGlyphId, const gfxMatrix& aSVGToAppSpace,
   1.134 +                         gfxRect *aResult);
   1.135 +
   1.136 +private:
   1.137 +    Element *GetGlyphElement(uint32_t aGlyphId);
   1.138 +
   1.139 +    nsClassHashtable<nsUint32HashKey, gfxSVGGlyphsDocument> mGlyphDocs;
   1.140 +    nsBaseHashtable<nsUint32HashKey, Element*, Element*> mGlyphIdMap;
   1.141 +
   1.142 +    hb_blob_t *mSVGData;
   1.143 +    gfxFontEntry *mFontEntry;
   1.144 +
   1.145 +    const struct Header {
   1.146 +        mozilla::AutoSwap_PRUint16 mVersion;
   1.147 +        mozilla::AutoSwap_PRUint32 mDocIndexOffset;
   1.148 +        mozilla::AutoSwap_PRUint32 mColorPalettesOffset;
   1.149 +    } *mHeader;
   1.150 +
   1.151 +    struct IndexEntry {
   1.152 +        mozilla::AutoSwap_PRUint16 mStartGlyph;
   1.153 +        mozilla::AutoSwap_PRUint16 mEndGlyph;
   1.154 +        mozilla::AutoSwap_PRUint32 mDocOffset;
   1.155 +        mozilla::AutoSwap_PRUint32 mDocLength;
   1.156 +    };
   1.157 +
   1.158 +    const struct DocIndex {
   1.159 +      mozilla::AutoSwap_PRUint16 mNumEntries;
   1.160 +      IndexEntry mEntries[1]; /* actual length = mNumEntries */
   1.161 +    } *mDocIndex;
   1.162 +
   1.163 +    static int CompareIndexEntries(const void *_a, const void *_b);
   1.164 +};
   1.165 +
   1.166 +/**
   1.167 + * Used for trickling down paint information through to SVG glyphs.
   1.168 + */
   1.169 +class gfxTextContextPaint
   1.170 +{
   1.171 +protected:
   1.172 +    gfxTextContextPaint() { }
   1.173 +
   1.174 +public:
   1.175 +    static mozilla::gfx::UserDataKey sUserDataKey;
   1.176 +
   1.177 +    /*
   1.178 +     * Get text context pattern with the specified opacity value.
   1.179 +     * This lets us inherit paints and paint opacities (i.e. fill/stroke and
   1.180 +     * fill-opacity/stroke-opacity) separately.
   1.181 +     */
   1.182 +    virtual already_AddRefed<gfxPattern> GetFillPattern(float aOpacity,
   1.183 +                                                        const gfxMatrix& aCTM) = 0;
   1.184 +    virtual already_AddRefed<gfxPattern> GetStrokePattern(float aOpacity,
   1.185 +                                                          const gfxMatrix& aCTM) = 0;
   1.186 +
   1.187 +    virtual float GetFillOpacity() { return 1.0f; }
   1.188 +    virtual float GetStrokeOpacity() { return 1.0f; }
   1.189 +
   1.190 +    void InitStrokeGeometry(gfxContext *aContext,
   1.191 +                            float devUnitsPerSVGUnit);
   1.192 +
   1.193 +    FallibleTArray<gfxFloat>& GetStrokeDashArray() {
   1.194 +        return mDashes;
   1.195 +    }
   1.196 +
   1.197 +    gfxFloat GetStrokeDashOffset() {
   1.198 +        return mDashOffset;
   1.199 +    }
   1.200 +
   1.201 +    gfxFloat GetStrokeWidth() {
   1.202 +        return mStrokeWidth;
   1.203 +    }
   1.204 +
   1.205 +    already_AddRefed<gfxPattern> GetFillPattern(const gfxMatrix& aCTM) {
   1.206 +        return GetFillPattern(GetFillOpacity(), aCTM);
   1.207 +    }
   1.208 +
   1.209 +    already_AddRefed<gfxPattern> GetStrokePattern(const gfxMatrix& aCTM) {
   1.210 +        return GetStrokePattern(GetStrokeOpacity(), aCTM);
   1.211 +    }
   1.212 +
   1.213 +    virtual ~gfxTextContextPaint() { }
   1.214 +
   1.215 +private:
   1.216 +    FallibleTArray<gfxFloat> mDashes;
   1.217 +    gfxFloat mDashOffset;
   1.218 +    gfxFloat mStrokeWidth;
   1.219 +};
   1.220 +
   1.221 +/**
   1.222 + * For passing in patterns where the text context has no separate pattern
   1.223 + * opacity value.
   1.224 + */
   1.225 +class SimpleTextContextPaint : public gfxTextContextPaint
   1.226 +{
   1.227 +private:
   1.228 +    static const gfxRGBA sZero;
   1.229 +
   1.230 +public:
   1.231 +    static gfxMatrix SetupDeviceToPatternMatrix(gfxPattern *aPattern,
   1.232 +                                                const gfxMatrix& aCTM)
   1.233 +    {
   1.234 +        if (!aPattern) {
   1.235 +            return gfxMatrix();
   1.236 +        }
   1.237 +        gfxMatrix deviceToUser = aCTM;
   1.238 +        deviceToUser.Invert();
   1.239 +        return deviceToUser * aPattern->GetMatrix();
   1.240 +    }
   1.241 +
   1.242 +    SimpleTextContextPaint(gfxPattern *aFillPattern, gfxPattern *aStrokePattern,
   1.243 +                          const gfxMatrix& aCTM) :
   1.244 +        mFillPattern(aFillPattern ? aFillPattern : new gfxPattern(sZero)),
   1.245 +        mStrokePattern(aStrokePattern ? aStrokePattern : new gfxPattern(sZero))
   1.246 +    {
   1.247 +        mFillMatrix = SetupDeviceToPatternMatrix(aFillPattern, aCTM);
   1.248 +        mStrokeMatrix = SetupDeviceToPatternMatrix(aStrokePattern, aCTM);
   1.249 +    }
   1.250 +
   1.251 +    already_AddRefed<gfxPattern> GetFillPattern(float aOpacity,
   1.252 +                                                const gfxMatrix& aCTM) {
   1.253 +        if (mFillPattern) {
   1.254 +            mFillPattern->SetMatrix(aCTM * mFillMatrix);
   1.255 +        }
   1.256 +        nsRefPtr<gfxPattern> fillPattern = mFillPattern;
   1.257 +        return fillPattern.forget();
   1.258 +    }
   1.259 +
   1.260 +    already_AddRefed<gfxPattern> GetStrokePattern(float aOpacity,
   1.261 +                                                  const gfxMatrix& aCTM) {
   1.262 +        if (mStrokePattern) {
   1.263 +            mStrokePattern->SetMatrix(aCTM * mStrokeMatrix);
   1.264 +        }
   1.265 +        nsRefPtr<gfxPattern> strokePattern = mStrokePattern;
   1.266 +        return strokePattern.forget();
   1.267 +    }
   1.268 +
   1.269 +    float GetFillOpacity() {
   1.270 +        return mFillPattern ? 1.0f : 0.0f;
   1.271 +    }
   1.272 +
   1.273 +    float GetStrokeOpacity() {
   1.274 +        return mStrokePattern ? 1.0f : 0.0f;
   1.275 +    }
   1.276 +
   1.277 +private:
   1.278 +    nsRefPtr<gfxPattern> mFillPattern;
   1.279 +    nsRefPtr<gfxPattern> mStrokePattern;
   1.280 +
   1.281 +    // Device space to pattern space transforms
   1.282 +    gfxMatrix mFillMatrix;
   1.283 +    gfxMatrix mStrokeMatrix;
   1.284 +};
   1.285 +
   1.286 +#endif

mercurial