Home | History | Annotate | Download | only in pdf
      1 /*
      2  * Copyright 2015 Google Inc.
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 #ifndef SkPDFCanon_DEFINED
      8 #define SkPDFCanon_DEFINED
      9 
     10 #include "SkBitmap.h"
     11 #include "SkPDFGraphicState.h"
     12 #include "SkPDFShader.h"
     13 #include "SkPixelSerializer.h"
     14 #include "SkTDArray.h"
     15 #include "SkTHash.h"
     16 
     17 class SkPDFFont;
     18 class SkPaint;
     19 class SkImage;
     20 
     21 class SkBitmapKey {
     22 public:
     23     SkBitmapKey() : fSubset(SkIRect::MakeEmpty()), fGenID(0) {}
     24     explicit SkBitmapKey(const SkBitmap& bm)
     25         : fSubset(bm.getSubset()), fGenID(bm.getGenerationID()) {}
     26     bool operator==(const SkBitmapKey& rhs) const {
     27         return fGenID == rhs.fGenID && fSubset == rhs.fSubset;
     28     }
     29 
     30 private:
     31     SkIRect fSubset;
     32     uint32_t fGenID;
     33 };
     34 
     35 /**
     36  *  The SkPDFCanon canonicalizes objects across PDF pages(SkPDFDevices).
     37  *
     38  *  The PDF backend works correctly if:
     39  *  -  There is no more than one SkPDFCanon for each thread.
     40  *  -  Every SkPDFDevice is given a pointer to a SkPDFCanon on creation.
     41  *  -  All SkPDFDevices in a document share the same SkPDFCanon.
     42  *  The SkDocument_PDF class makes this happen by owning a single
     43  *  SkPDFCanon.
     44  *
     45  *  The addFoo() methods will ref the Foo; the canon's destructor will
     46  *  call foo->unref() on all of these objects.
     47  *
     48  *  The findFoo() methods do not change the ref count of the Foo
     49  *  objects.
     50  */
     51 class SkPDFCanon : SkNoncopyable {
     52 public:
     53     ~SkPDFCanon() { this->reset(); }
     54 
     55     // reset to original setting, unrefs all objects.
     56     void reset();
     57 
     58     // Returns exact match if there is one.  If not, it returns nullptr.
     59     // If there is no exact match, but there is a related font, we
     60     // still return nullptr, but also set *relatedFont.
     61     SkPDFFont* findFont(uint32_t fontID,
     62                         uint16_t glyphID,
     63                         SkPDFFont** relatedFont) const;
     64     void addFont(SkPDFFont* font, uint32_t fontID, uint16_t fGlyphID);
     65 
     66     SkPDFFunctionShader* findFunctionShader(const SkPDFShader::State&) const;
     67     void addFunctionShader(SkPDFFunctionShader*);
     68 
     69     SkPDFAlphaFunctionShader* findAlphaShader(const SkPDFShader::State&) const;
     70     void addAlphaShader(SkPDFAlphaFunctionShader*);
     71 
     72     SkPDFImageShader* findImageShader(const SkPDFShader::State&) const;
     73     void addImageShader(SkPDFImageShader*);
     74 
     75     const SkPDFGraphicState* findGraphicState(const SkPDFGraphicState&) const;
     76     void addGraphicState(const SkPDFGraphicState*);
     77 
     78     SkPDFObject* findPDFBitmap(const SkImage* image) const;
     79     void addPDFBitmap(uint32_t imageUniqueID, SkPDFObject*);
     80     const SkImage* bitmapToImage(const SkBitmap&);
     81 
     82     SkTHashMap<uint32_t, bool> fCanEmbedTypeface;
     83 
     84     SkAutoTUnref<SkPixelSerializer> fPixelSerializer;
     85 
     86 private:
     87     struct FontRec {
     88         SkPDFFont* fFont;
     89         uint32_t fFontID;
     90         uint16_t fGlyphID;
     91     };
     92     SkTDArray<FontRec> fFontRecords;
     93 
     94     SkTDArray<SkPDFFunctionShader*> fFunctionShaderRecords;
     95 
     96     SkTDArray<SkPDFAlphaFunctionShader*> fAlphaShaderRecords;
     97 
     98     SkTDArray<SkPDFImageShader*> fImageShaderRecords;
     99 
    100     struct WrapGS {
    101         explicit WrapGS(const SkPDFGraphicState* ptr = nullptr) : fPtr(ptr) {}
    102         const SkPDFGraphicState* fPtr;
    103         bool operator==(const WrapGS& rhs) const {
    104             SkASSERT(fPtr);
    105             SkASSERT(rhs.fPtr);
    106             return *fPtr == *rhs.fPtr;
    107         }
    108         struct Hash {
    109             uint32_t operator()(const WrapGS& w) const {
    110                 SkASSERT(w.fPtr);
    111                 return w.fPtr->hash();
    112             }
    113         };
    114     };
    115     SkTHashSet<WrapGS, WrapGS::Hash> fGraphicStateRecords;
    116 
    117     SkTHashMap<SkBitmapKey, const SkImage*> fBitmapToImageMap;
    118     SkTHashMap<uint32_t /*ImageUniqueID*/, SkPDFObject*> fPDFBitmapMap;
    119 };
    120 #endif  // SkPDFCanon_DEFINED
    121