tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

gfxSVGGlyphs.h (7619B)


      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 "nsRefreshObservers.h"
     18 
     19 class nsIDocumentViewer;
     20 class gfxSVGGlyphs;
     21 
     22 namespace mozilla {
     23 class PresShell;
     24 class SVGContextPaint;
     25 namespace dom {
     26 class Document;
     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  typedef mozilla::dom::Element Element;
     41 
     42 public:
     43  gfxSVGGlyphsDocument(const uint8_t* aBuffer, uint32_t aBufLen,
     44                       gfxSVGGlyphs* aSVGGlyphs);
     45 
     46  Element* GetGlyphElement(uint32_t aGlyphId);
     47 
     48  ~gfxSVGGlyphsDocument();
     49 
     50  void DidRefresh() override;
     51 
     52  size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
     53 
     54 private:
     55  nsresult ParseDocument(const uint8_t* aBuffer, uint32_t aBufLen);
     56 
     57  nsresult SetupPresentation();
     58 
     59  void FindGlyphElements(Element* aElement);
     60 
     61  void InsertGlyphId(Element* aGlyphElement);
     62 
     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<nsIDocumentViewer> mViewer;
     67  RefPtr<mozilla::PresShell> mPresShell;
     68 
     69  nsBaseHashtable<nsUint32HashKey, Element*, Element*> mGlyphIdMap;
     70 };
     71 
     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.
     77 */
     78 class gfxSVGGlyphs {
     79 private:
     80  typedef mozilla::dom::Element Element;
     81 
     82 public:
     83  /**
     84   * @param aSVGTable The SVG table from the OpenType font
     85   *
     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.
     89   */
     90  gfxSVGGlyphs(hb_blob_t* aSVGTable, gfxFontEntry* aFontEntry);
     91 
     92  /**
     93   * Releases our references to the SVG table and cleans up everything else.
     94   */
     95  ~gfxSVGGlyphs();
     96 
     97  /**
     98   * This is called when the refresh driver has ticked.
     99   */
    100  void DidRefresh();
    101 
    102  /**
    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.
    107   */
    108  gfxSVGGlyphsDocument* FindOrCreateGlyphsDocument(uint32_t aGlyphId);
    109 
    110  /**
    111   * Return true iff there is an SVG glyph for |aGlyphId|
    112   */
    113  bool HasSVGGlyph(uint32_t aGlyphId);
    114 
    115  /**
    116   * Render the SVG glyph for |aGlyphId|
    117   * @param aContextPaint Information on text context paints.
    118   *   See |SVGContextPaint|.
    119   */
    120  void RenderGlyph(gfxContext* aContext, uint32_t aGlyphId,
    121                   mozilla::SVGContextPaint* aContextPaint);
    122 
    123  /**
    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
    127   */
    128  bool GetGlyphExtents(uint32_t aGlyphId, const gfxMatrix& aSVGToAppSpace,
    129                       gfxRect* aResult);
    130 
    131  size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
    132 
    133  gfxFontEntry* FontEntry() const { return mFontEntry; }
    134 
    135 private:
    136  Element* GetGlyphElement(uint32_t aGlyphId);
    137 
    138  nsClassHashtable<nsUint32HashKey, gfxSVGGlyphsDocument> mGlyphDocs;
    139  nsBaseHashtable<nsUint32HashKey, Element*, Element*> mGlyphIdMap;
    140 
    141  hb_blob_t* mSVGData;
    142 
    143  // pointer to the font entry that owns this gfxSVGGlyphs object
    144  gfxFontEntry* MOZ_NON_OWNING_REF mFontEntry;
    145 
    146  const struct Header {
    147    mozilla::AutoSwap_PRUint16 mVersion;
    148    mozilla::AutoSwap_PRUint32 mDocIndexOffset;
    149    mozilla::AutoSwap_PRUint32 mColorPalettesOffset;
    150  }* mHeader;
    151 
    152  struct IndexEntry {
    153    mozilla::AutoSwap_PRUint16 mStartGlyph;
    154    mozilla::AutoSwap_PRUint16 mEndGlyph;
    155    mozilla::AutoSwap_PRUint32 mDocOffset;
    156    mozilla::AutoSwap_PRUint32 mDocLength;
    157  };
    158 
    159  const struct DocIndex {
    160    mozilla::AutoSwap_PRUint16 mNumEntries;
    161    IndexEntry mEntries[1]; /* actual length = mNumEntries */
    162  }* mDocIndex;
    163 
    164  static int CompareIndexEntries(const void* _a, const void* _b);
    165 };
    166 
    167 /**
    168 * XXX This is a complete hack and should die (see bug 1291494).
    169 *
    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.
    177 */
    178 class SimpleTextContextPaint : public mozilla::SVGContextPaint {
    179 private:
    180  static constexpr mozilla::gfx::DeviceColor sZero{};
    181 
    182  static gfxMatrix SetupDeviceToPatternMatrix(gfxPattern* aPattern,
    183                                              const gfxMatrix& aCTM) {
    184    if (!aPattern) {
    185      return gfxMatrix();
    186    }
    187    gfxMatrix deviceToUser = aCTM;
    188    if (!deviceToUser.Invert()) {
    189      return gfxMatrix(0, 0, 0, 0, 0, 0);  // singular
    190    }
    191    return deviceToUser * aPattern->GetMatrix();
    192  }
    193 
    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);
    202  }
    203 
    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);
    209    }
    210    RefPtr<gfxPattern> fillPattern = mFillPattern;
    211    return fillPattern.forget();
    212  }
    213 
    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);
    219    }
    220    RefPtr<gfxPattern> strokePattern = mStrokePattern;
    221    return strokePattern.forget();
    222  }
    223 
    224  float GetFillOpacity() const override { return mFillPattern ? 1.0f : 0.0f; }
    225 
    226  float GetStrokeOpacity() const override {
    227    return mStrokePattern ? 1.0f : 0.0f;
    228  }
    229 
    230 private:
    231  RefPtr<gfxPattern> mFillPattern;
    232  RefPtr<gfxPattern> mStrokePattern;
    233 
    234  // Device space to pattern space transforms
    235  gfxMatrix mFillMatrix;
    236  gfxMatrix mStrokeMatrix;
    237 };
    238 
    239 #endif