1*c8dee2aaSAndroid Build Coastguard Worker /* 2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2011 Google Inc. 3*c8dee2aaSAndroid Build Coastguard Worker * 4*c8dee2aaSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license that can be 5*c8dee2aaSAndroid Build Coastguard Worker * found in the LICENSE file. 6*c8dee2aaSAndroid Build Coastguard Worker */ 7*c8dee2aaSAndroid Build Coastguard Worker 8*c8dee2aaSAndroid Build Coastguard Worker #ifndef SkPDFDevice_DEFINED 9*c8dee2aaSAndroid Build Coastguard Worker #define SkPDFDevice_DEFINED 10*c8dee2aaSAndroid Build Coastguard Worker 11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkCanvas.h" 12*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkMatrix.h" 13*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRefCnt.h" 14*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkSamplingOptions.h" 15*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkScalar.h" 16*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkStream.h" 17*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkClipStack.h" 18*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkClipStackDevice.h" 19*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkTHash.h" 20*c8dee2aaSAndroid Build Coastguard Worker #include "src/pdf/SkKeyedImage.h" 21*c8dee2aaSAndroid Build Coastguard Worker #include "src/pdf/SkPDFGraphicStackState.h" 22*c8dee2aaSAndroid Build Coastguard Worker #include "src/pdf/SkPDFTag.h" 23*c8dee2aaSAndroid Build Coastguard Worker #include "src/pdf/SkPDFTypes.h" 24*c8dee2aaSAndroid Build Coastguard Worker 25*c8dee2aaSAndroid Build Coastguard Worker #include <cstddef> 26*c8dee2aaSAndroid Build Coastguard Worker #include <memory> 27*c8dee2aaSAndroid Build Coastguard Worker 28*c8dee2aaSAndroid Build Coastguard Worker class SkBitmap; 29*c8dee2aaSAndroid Build Coastguard Worker class SkBlender; 30*c8dee2aaSAndroid Build Coastguard Worker class SkData; 31*c8dee2aaSAndroid Build Coastguard Worker class SkDevice; 32*c8dee2aaSAndroid Build Coastguard Worker class SkImage; 33*c8dee2aaSAndroid Build Coastguard Worker class SkMesh; 34*c8dee2aaSAndroid Build Coastguard Worker class SkPDFDocument; 35*c8dee2aaSAndroid Build Coastguard Worker class SkPaint; 36*c8dee2aaSAndroid Build Coastguard Worker class SkPath; 37*c8dee2aaSAndroid Build Coastguard Worker class SkRRect; 38*c8dee2aaSAndroid Build Coastguard Worker class SkSpecialImage; 39*c8dee2aaSAndroid Build Coastguard Worker class SkSurface; 40*c8dee2aaSAndroid Build Coastguard Worker class SkSurfaceProps; 41*c8dee2aaSAndroid Build Coastguard Worker class SkVertices; 42*c8dee2aaSAndroid Build Coastguard Worker enum class SkBlendMode; 43*c8dee2aaSAndroid Build Coastguard Worker struct SkIRect; 44*c8dee2aaSAndroid Build Coastguard Worker struct SkISize; 45*c8dee2aaSAndroid Build Coastguard Worker struct SkImageInfo; 46*c8dee2aaSAndroid Build Coastguard Worker struct SkPoint; 47*c8dee2aaSAndroid Build Coastguard Worker struct SkRect; 48*c8dee2aaSAndroid Build Coastguard Worker 49*c8dee2aaSAndroid Build Coastguard Worker namespace sktext { 50*c8dee2aaSAndroid Build Coastguard Worker class GlyphRun; 51*c8dee2aaSAndroid Build Coastguard Worker class GlyphRunList; 52*c8dee2aaSAndroid Build Coastguard Worker } 53*c8dee2aaSAndroid Build Coastguard Worker 54*c8dee2aaSAndroid Build Coastguard Worker /** 55*c8dee2aaSAndroid Build Coastguard Worker * \class SkPDFDevice 56*c8dee2aaSAndroid Build Coastguard Worker * 57*c8dee2aaSAndroid Build Coastguard Worker * An SkPDFDevice is the drawing context for a page or layer of PDF 58*c8dee2aaSAndroid Build Coastguard Worker * content. 59*c8dee2aaSAndroid Build Coastguard Worker */ 60*c8dee2aaSAndroid Build Coastguard Worker class SkPDFDevice final : public SkClipStackDevice { 61*c8dee2aaSAndroid Build Coastguard Worker public: 62*c8dee2aaSAndroid Build Coastguard Worker /** 63*c8dee2aaSAndroid Build Coastguard Worker * @param pageSize Page size in point units. 64*c8dee2aaSAndroid Build Coastguard Worker * 1 point == 127/360 mm == 1/72 inch 65*c8dee2aaSAndroid Build Coastguard Worker * @param document A non-null pointer back to the 66*c8dee2aaSAndroid Build Coastguard Worker * PDFDocument object. The document is responsible for 67*c8dee2aaSAndroid Build Coastguard Worker * de-duplicating across pages (via the SkPDFDocument) and 68*c8dee2aaSAndroid Build Coastguard Worker * for early serializing of large immutable objects, such 69*c8dee2aaSAndroid Build Coastguard Worker * as images (via SkPDFDocument::serialize()). 70*c8dee2aaSAndroid Build Coastguard Worker * @param initialTransform Transform to be applied to the entire page. 71*c8dee2aaSAndroid Build Coastguard Worker */ 72*c8dee2aaSAndroid Build Coastguard Worker SkPDFDevice(SkISize pageSize, SkPDFDocument* document, 73*c8dee2aaSAndroid Build Coastguard Worker const SkMatrix& initialTransform = SkMatrix::I()); 74*c8dee2aaSAndroid Build Coastguard Worker makeCongruentDevice()75*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkPDFDevice> makeCongruentDevice() { 76*c8dee2aaSAndroid Build Coastguard Worker return sk_make_sp<SkPDFDevice>(this->size(), fDocument); 77*c8dee2aaSAndroid Build Coastguard Worker } 78*c8dee2aaSAndroid Build Coastguard Worker 79*c8dee2aaSAndroid Build Coastguard Worker ~SkPDFDevice() override; 80*c8dee2aaSAndroid Build Coastguard Worker 81*c8dee2aaSAndroid Build Coastguard Worker /** 82*c8dee2aaSAndroid Build Coastguard Worker * These are called inside the per-device-layer loop for each draw call. 83*c8dee2aaSAndroid Build Coastguard Worker * When these are called, we have already applied any saveLayer 84*c8dee2aaSAndroid Build Coastguard Worker * operations, and are handling any looping from the paint. 85*c8dee2aaSAndroid Build Coastguard Worker */ 86*c8dee2aaSAndroid Build Coastguard Worker void drawPaint(const SkPaint& paint) override; 87*c8dee2aaSAndroid Build Coastguard Worker void drawPoints(SkCanvas::PointMode mode, 88*c8dee2aaSAndroid Build Coastguard Worker size_t count, const SkPoint[], 89*c8dee2aaSAndroid Build Coastguard Worker const SkPaint& paint) override; 90*c8dee2aaSAndroid Build Coastguard Worker void drawRect(const SkRect& r, const SkPaint& paint) override; 91*c8dee2aaSAndroid Build Coastguard Worker void drawOval(const SkRect& oval, const SkPaint& paint) override; 92*c8dee2aaSAndroid Build Coastguard Worker void drawRRect(const SkRRect& rr, const SkPaint& paint) override; 93*c8dee2aaSAndroid Build Coastguard Worker void drawPath(const SkPath& origpath, const SkPaint& paint, bool pathIsMutable) override; 94*c8dee2aaSAndroid Build Coastguard Worker 95*c8dee2aaSAndroid Build Coastguard Worker void drawImageRect(const SkImage*, 96*c8dee2aaSAndroid Build Coastguard Worker const SkRect* src, 97*c8dee2aaSAndroid Build Coastguard Worker const SkRect& dst, 98*c8dee2aaSAndroid Build Coastguard Worker const SkSamplingOptions&, 99*c8dee2aaSAndroid Build Coastguard Worker const SkPaint&, 100*c8dee2aaSAndroid Build Coastguard Worker SkCanvas::SrcRectConstraint) override; 101*c8dee2aaSAndroid Build Coastguard Worker 102*c8dee2aaSAndroid Build Coastguard Worker void drawVertices(const SkVertices*, sk_sp<SkBlender>, const SkPaint&, bool) override; 103*c8dee2aaSAndroid Build Coastguard Worker void drawMesh(const SkMesh&, sk_sp<SkBlender>, const SkPaint&) override; 104*c8dee2aaSAndroid Build Coastguard Worker 105*c8dee2aaSAndroid Build Coastguard Worker void drawAnnotation(const SkRect&, const char key[], SkData* value) override; 106*c8dee2aaSAndroid Build Coastguard Worker 107*c8dee2aaSAndroid Build Coastguard Worker void drawDevice(SkDevice*, const SkSamplingOptions&, const SkPaint&) override; 108*c8dee2aaSAndroid Build Coastguard Worker void drawSpecial(SkSpecialImage*, const SkMatrix&, const SkSamplingOptions&, 109*c8dee2aaSAndroid Build Coastguard Worker const SkPaint&, SkCanvas::SrcRectConstraint) override; 110*c8dee2aaSAndroid Build Coastguard Worker 111*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkSurface> makeSurface(const SkImageInfo&, const SkSurfaceProps&) override; 112*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkDevice> createDevice(const CreateInfo&, const SkPaint*) override; 113*c8dee2aaSAndroid Build Coastguard Worker 114*c8dee2aaSAndroid Build Coastguard Worker // PDF specific methods. 115*c8dee2aaSAndroid Build Coastguard Worker void drawSprite(const SkBitmap& bitmap, int x, int y, 116*c8dee2aaSAndroid Build Coastguard Worker const SkPaint& paint); 117*c8dee2aaSAndroid Build Coastguard Worker 118*c8dee2aaSAndroid Build Coastguard Worker /** Create the resource dictionary for this device. Destructive. */ 119*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<SkPDFDict> makeResourceDict(); 120*c8dee2aaSAndroid Build Coastguard Worker 121*c8dee2aaSAndroid Build Coastguard Worker /** Returns a SkStream with the page contents. 122*c8dee2aaSAndroid Build Coastguard Worker */ 123*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<SkStreamAsset> content(); 124*c8dee2aaSAndroid Build Coastguard Worker initialTransform()125*c8dee2aaSAndroid Build Coastguard Worker const SkMatrix& initialTransform() const { return fInitialTransform; } 126*c8dee2aaSAndroid Build Coastguard Worker 127*c8dee2aaSAndroid Build Coastguard Worker protected: 128*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkSpecialImage> makeSpecial(const SkBitmap&) override; 129*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkSpecialImage> makeSpecial(const SkImage*) override; 130*c8dee2aaSAndroid Build Coastguard Worker 131*c8dee2aaSAndroid Build Coastguard Worker private: 132*c8dee2aaSAndroid Build Coastguard Worker // TODO(vandebo): push most of SkPDFDevice's state into a core object in 133*c8dee2aaSAndroid Build Coastguard Worker // order to get the right access levels without using friend. 134*c8dee2aaSAndroid Build Coastguard Worker friend class ScopedContentEntry; 135*c8dee2aaSAndroid Build Coastguard Worker 136*c8dee2aaSAndroid Build Coastguard Worker SkMatrix fInitialTransform; 137*c8dee2aaSAndroid Build Coastguard Worker 138*c8dee2aaSAndroid Build Coastguard Worker skia_private::THashSet<SkPDFIndirectReference> fGraphicStateResources; 139*c8dee2aaSAndroid Build Coastguard Worker skia_private::THashSet<SkPDFIndirectReference> fXObjectResources; 140*c8dee2aaSAndroid Build Coastguard Worker skia_private::THashSet<SkPDFIndirectReference> fShaderResources; 141*c8dee2aaSAndroid Build Coastguard Worker skia_private::THashSet<SkPDFIndirectReference> fFontResources; 142*c8dee2aaSAndroid Build Coastguard Worker 143*c8dee2aaSAndroid Build Coastguard Worker class MarkedContentManager { 144*c8dee2aaSAndroid Build Coastguard Worker public: 145*c8dee2aaSAndroid Build Coastguard Worker MarkedContentManager(SkPDFDocument* document, SkDynamicMemoryWStream* out); 146*c8dee2aaSAndroid Build Coastguard Worker ~MarkedContentManager(); 147*c8dee2aaSAndroid Build Coastguard Worker 148*c8dee2aaSAndroid Build Coastguard Worker // Sets the current element identifier. Associate future draws with the structure element 149*c8dee2aaSAndroid Build Coastguard Worker // with the given element identifier. Element identifier 0 is reserved to mean no structure 150*c8dee2aaSAndroid Build Coastguard Worker // element. 151*c8dee2aaSAndroid Build Coastguard Worker void setNextMarksElemId(int nextMarksElemId); 152*c8dee2aaSAndroid Build Coastguard Worker 153*c8dee2aaSAndroid Build Coastguard Worker // The current element identifier. 154*c8dee2aaSAndroid Build Coastguard Worker int elemId() const; 155*c8dee2aaSAndroid Build Coastguard Worker 156*c8dee2aaSAndroid Build Coastguard Worker // Starts a marked-content sequence for a content item for the structure element with the 157*c8dee2aaSAndroid Build Coastguard Worker // current element identifier. If there is an active marked-content sequence associated with 158*c8dee2aaSAndroid Build Coastguard Worker // a different element identifier the active marked-content sequence will first be closed. 159*c8dee2aaSAndroid Build Coastguard Worker // If there is no structure element with the current element identifier then the 160*c8dee2aaSAndroid Build Coastguard Worker // marked-content sequence will not be started. 161*c8dee2aaSAndroid Build Coastguard Worker void beginMark(); 162*c8dee2aaSAndroid Build Coastguard Worker 163*c8dee2aaSAndroid Build Coastguard Worker // Tests if there is an active marked-content sequence. 164*c8dee2aaSAndroid Build Coastguard Worker bool hasActiveMark() const; 165*c8dee2aaSAndroid Build Coastguard Worker 166*c8dee2aaSAndroid Build Coastguard Worker // Accumulates an upper left location for the active mark. The point is in PDF page space 167*c8dee2aaSAndroid Build Coastguard Worker // and so is y-up. Only use if this.hasActiveMark() 168*c8dee2aaSAndroid Build Coastguard Worker void accumulate(const SkPoint& p); 169*c8dee2aaSAndroid Build Coastguard Worker 170*c8dee2aaSAndroid Build Coastguard Worker // Tests if this marked content manager made any marks. madeMarks()171*c8dee2aaSAndroid Build Coastguard Worker bool madeMarks() const { return fMadeMarks; } 172*c8dee2aaSAndroid Build Coastguard Worker 173*c8dee2aaSAndroid Build Coastguard Worker private: 174*c8dee2aaSAndroid Build Coastguard Worker SkPDFDocument* fDoc; 175*c8dee2aaSAndroid Build Coastguard Worker SkDynamicMemoryWStream* fOut; 176*c8dee2aaSAndroid Build Coastguard Worker SkPDFStructTree::Mark fCurrentlyActiveMark; 177*c8dee2aaSAndroid Build Coastguard Worker int fNextMarksElemId; 178*c8dee2aaSAndroid Build Coastguard Worker bool fMadeMarks; 179*c8dee2aaSAndroid Build Coastguard Worker } fMarkManager; 180*c8dee2aaSAndroid Build Coastguard Worker 181*c8dee2aaSAndroid Build Coastguard Worker SkDynamicMemoryWStream fContent; 182*c8dee2aaSAndroid Build Coastguard Worker SkDynamicMemoryWStream fContentBuffer; 183*c8dee2aaSAndroid Build Coastguard Worker bool fNeedsExtraSave = false; 184*c8dee2aaSAndroid Build Coastguard Worker SkPDFGraphicStackState fActiveStackState; 185*c8dee2aaSAndroid Build Coastguard Worker SkPDFDocument* fDocument; 186*c8dee2aaSAndroid Build Coastguard Worker 187*c8dee2aaSAndroid Build Coastguard Worker //////////////////////////////////////////////////////////////////////////// 188*c8dee2aaSAndroid Build Coastguard Worker 189*c8dee2aaSAndroid Build Coastguard Worker void onDrawGlyphRunList(SkCanvas*, const sktext::GlyphRunList&, const SkPaint& paint) override; 190*c8dee2aaSAndroid Build Coastguard Worker 191*c8dee2aaSAndroid Build Coastguard Worker // Set alpha to true if making a transparency group form x-objects. 192*c8dee2aaSAndroid Build Coastguard Worker SkPDFIndirectReference makeFormXObjectFromDevice(bool alpha = false); 193*c8dee2aaSAndroid Build Coastguard Worker SkPDFIndirectReference makeFormXObjectFromDevice(SkIRect bbox, bool alpha = false); 194*c8dee2aaSAndroid Build Coastguard Worker 195*c8dee2aaSAndroid Build Coastguard Worker void drawFormXObjectWithMask(SkPDFIndirectReference xObject, 196*c8dee2aaSAndroid Build Coastguard Worker SkPDFIndirectReference sMask, 197*c8dee2aaSAndroid Build Coastguard Worker SkBlendMode, 198*c8dee2aaSAndroid Build Coastguard Worker bool invertClip); 199*c8dee2aaSAndroid Build Coastguard Worker 200*c8dee2aaSAndroid Build Coastguard Worker // If the paint or clip is such that we shouldn't draw anything, this 201*c8dee2aaSAndroid Build Coastguard Worker // returns nullptr and does not create a content entry. 202*c8dee2aaSAndroid Build Coastguard Worker // setUpContentEntry and finishContentEntry can be used directly, but 203*c8dee2aaSAndroid Build Coastguard Worker // the preferred method is to use the ScopedContentEntry helper class. 204*c8dee2aaSAndroid Build Coastguard Worker SkDynamicMemoryWStream* setUpContentEntry(const SkClipStack* clipStack, 205*c8dee2aaSAndroid Build Coastguard Worker const SkMatrix& matrix, 206*c8dee2aaSAndroid Build Coastguard Worker const SkPaint& paint, 207*c8dee2aaSAndroid Build Coastguard Worker SkScalar, 208*c8dee2aaSAndroid Build Coastguard Worker SkPDFIndirectReference* dst); 209*c8dee2aaSAndroid Build Coastguard Worker void finishContentEntry(const SkClipStack*, SkBlendMode, SkPDFIndirectReference, SkPath*); 210*c8dee2aaSAndroid Build Coastguard Worker bool isContentEmpty(); 211*c8dee2aaSAndroid Build Coastguard Worker 212*c8dee2aaSAndroid Build Coastguard Worker void internalDrawGlyphRun( 213*c8dee2aaSAndroid Build Coastguard Worker const sktext::GlyphRun& glyphRun, SkPoint offset, const SkPaint& runPaint); 214*c8dee2aaSAndroid Build Coastguard Worker void drawGlyphRunAsPath( 215*c8dee2aaSAndroid Build Coastguard Worker const sktext::GlyphRun& glyphRun, SkPoint offset, const SkPaint& runPaint); 216*c8dee2aaSAndroid Build Coastguard Worker 217*c8dee2aaSAndroid Build Coastguard Worker void internalDrawImageRect(SkKeyedImage, 218*c8dee2aaSAndroid Build Coastguard Worker const SkRect* src, 219*c8dee2aaSAndroid Build Coastguard Worker const SkRect& dst, 220*c8dee2aaSAndroid Build Coastguard Worker const SkSamplingOptions&, 221*c8dee2aaSAndroid Build Coastguard Worker const SkPaint&, 222*c8dee2aaSAndroid Build Coastguard Worker const SkMatrix& canvasTransformationMatrix); 223*c8dee2aaSAndroid Build Coastguard Worker 224*c8dee2aaSAndroid Build Coastguard Worker void internalDrawPath(const SkClipStack&, 225*c8dee2aaSAndroid Build Coastguard Worker const SkMatrix&, 226*c8dee2aaSAndroid Build Coastguard Worker const SkPath&, 227*c8dee2aaSAndroid Build Coastguard Worker const SkPaint&, 228*c8dee2aaSAndroid Build Coastguard Worker bool pathIsMutable); 229*c8dee2aaSAndroid Build Coastguard Worker 230*c8dee2aaSAndroid Build Coastguard Worker void internalDrawPathWithFilter(const SkClipStack& clipStack, 231*c8dee2aaSAndroid Build Coastguard Worker const SkMatrix& ctm, 232*c8dee2aaSAndroid Build Coastguard Worker const SkPath& origPath, 233*c8dee2aaSAndroid Build Coastguard Worker const SkPaint& paint); 234*c8dee2aaSAndroid Build Coastguard Worker 235*c8dee2aaSAndroid Build Coastguard Worker bool handleInversePath(const SkPath& origPath, const SkPaint& paint, bool pathIsMutable); 236*c8dee2aaSAndroid Build Coastguard Worker 237*c8dee2aaSAndroid Build Coastguard Worker void clearMaskOnGraphicState(SkDynamicMemoryWStream*); 238*c8dee2aaSAndroid Build Coastguard Worker void setGraphicState(SkPDFIndirectReference gs, SkDynamicMemoryWStream*); 239*c8dee2aaSAndroid Build Coastguard Worker void drawFormXObject(SkPDFIndirectReference xObject, SkDynamicMemoryWStream*, SkPath* shape); 240*c8dee2aaSAndroid Build Coastguard Worker hasEmptyClip()241*c8dee2aaSAndroid Build Coastguard Worker bool hasEmptyClip() const { return this->cs().isEmpty(this->bounds()); } 242*c8dee2aaSAndroid Build Coastguard Worker 243*c8dee2aaSAndroid Build Coastguard Worker void reset(); 244*c8dee2aaSAndroid Build Coastguard Worker }; 245*c8dee2aaSAndroid Build Coastguard Worker 246*c8dee2aaSAndroid Build Coastguard Worker #endif 247