1 /* 2 * Copyright 2011 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 8 #ifndef SkPDFDevice_DEFINED 9 #define SkPDFDevice_DEFINED 10 11 #include "include/core/SkBitmap.h" 12 #include "include/core/SkCanvas.h" 13 #include "include/core/SkData.h" 14 #include "include/core/SkPaint.h" 15 #include "include/core/SkRect.h" 16 #include "include/core/SkRefCnt.h" 17 #include "include/core/SkStream.h" 18 #include "include/private/SkTHash.h" 19 #include "src/core/SkClipStack.h" 20 #include "src/core/SkClipStackDevice.h" 21 #include "src/core/SkTextBlobPriv.h" 22 #include "src/pdf/SkKeyedImage.h" 23 #include "src/pdf/SkPDFGraphicStackState.h" 24 #include "src/pdf/SkPDFTypes.h" 25 26 #include <vector> 27 28 class SkGlyphRunList; 29 class SkKeyedImage; 30 class SkPDFArray; 31 class SkPDFDevice; 32 class SkPDFDict; 33 class SkPDFDocument; 34 class SkPDFFont; 35 class SkPDFObject; 36 class SkPath; 37 class SkRRect; 38 struct SkPDFIndirectReference; 39 40 /** 41 * \class SkPDFDevice 42 * 43 * An SkPDFDevice is the drawing context for a page or layer of PDF 44 * content. 45 */ 46 class SkPDFDevice final : public SkClipStackDevice { 47 public: 48 /** 49 * @param pageSize Page size in point units. 50 * 1 point == 127/360 mm == 1/72 inch 51 * @param document A non-null pointer back to the 52 * PDFDocument object. The document is responsible for 53 * de-duplicating across pages (via the SkPDFDocument) and 54 * for early serializing of large immutable objects, such 55 * as images (via SkPDFDocument::serialize()). 56 * @param initialTransform Transform to be applied to the entire page. 57 */ 58 SkPDFDevice(SkISize pageSize, SkPDFDocument* document, 59 const SkMatrix& initialTransform = SkMatrix::I()); 60 makeCongruentDevice()61 sk_sp<SkPDFDevice> makeCongruentDevice() { 62 return sk_make_sp<SkPDFDevice>(this->size(), fDocument); 63 } 64 65 ~SkPDFDevice() override; 66 67 /** 68 * These are called inside the per-device-layer loop for each draw call. 69 * When these are called, we have already applied any saveLayer 70 * operations, and are handling any looping from the paint. 71 */ 72 void drawPaint(const SkPaint& paint) override; 73 void drawPoints(SkCanvas::PointMode mode, 74 size_t count, const SkPoint[], 75 const SkPaint& paint) override; 76 void drawRect(const SkRect& r, const SkPaint& paint) override; 77 void drawOval(const SkRect& oval, const SkPaint& paint) override; 78 void drawRRect(const SkRRect& rr, const SkPaint& paint) override; 79 void drawPath(const SkPath& origpath, const SkPaint& paint, bool pathIsMutable) override; 80 void drawBitmapRect(const SkBitmap& bitmap, const SkRect* src, 81 const SkRect& dst, const SkPaint&, SkCanvas::SrcRectConstraint) override; 82 void drawSprite(const SkBitmap& bitmap, int x, int y, 83 const SkPaint& paint) override; 84 85 void drawImageRect(const SkImage*, 86 const SkRect* src, 87 const SkRect& dst, 88 const SkPaint&, 89 SkCanvas::SrcRectConstraint) override; 90 void drawGlyphRunList(const SkGlyphRunList& glyphRunList) override; 91 void drawVertices(const SkVertices*, const SkVertices::Bone bones[], int boneCount, SkBlendMode, 92 const SkPaint&) override; 93 void drawDevice(SkBaseDevice*, int x, int y, 94 const SkPaint&) override; 95 96 // PDF specific methods. 97 98 /** Create the resource dictionary for this device. Destructive. */ 99 std::unique_ptr<SkPDFDict> makeResourceDict(); 100 101 /** Returns a SkStream with the page contents. 102 */ 103 std::unique_ptr<SkStreamAsset> content(); 104 size()105 SkISize size() const { return this->imageInfo().dimensions(); } bounds()106 SkIRect bounds() const { return this->imageInfo().bounds(); } 107 108 void DrawGlyphRunAsPath(SkPDFDevice* dev, const SkGlyphRun& glyphRun, SkPoint offset); 109 initialTransform()110 const SkMatrix& initialTransform() const { return fInitialTransform; } 111 112 protected: 113 sk_sp<SkSurface> makeSurface(const SkImageInfo&, const SkSurfaceProps&) override; 114 115 void drawAnnotation(const SkRect&, const char key[], SkData* value) override; 116 117 void drawSpecial(SkSpecialImage*, int x, int y, const SkPaint&, 118 SkImage*, const SkMatrix&) override; 119 sk_sp<SkSpecialImage> makeSpecial(const SkBitmap&) override; 120 sk_sp<SkSpecialImage> makeSpecial(const SkImage*) override; 121 sk_sp<SkSpecialImage> snapSpecial() override; 122 SkImageFilterCache* getImageFilterCache() override; 123 124 private: 125 // TODO(vandebo): push most of SkPDFDevice's state into a core object in 126 // order to get the right access levels without using friend. 127 friend class ScopedContentEntry; 128 129 SkMatrix fInitialTransform; 130 131 SkTHashSet<SkPDFIndirectReference> fGraphicStateResources; 132 SkTHashSet<SkPDFIndirectReference> fXObjectResources; 133 SkTHashSet<SkPDFIndirectReference> fShaderResources; 134 SkTHashSet<SkPDFIndirectReference> fFontResources; 135 int fNodeId; 136 137 SkDynamicMemoryWStream fContent; 138 SkDynamicMemoryWStream fContentBuffer; 139 bool fNeedsExtraSave = false; 140 SkPDFGraphicStackState fActiveStackState; 141 SkPDFDocument* fDocument; 142 143 //////////////////////////////////////////////////////////////////////////// 144 145 SkBaseDevice* onCreateDevice(const CreateInfo&, const SkPaint*) override; 146 147 // Set alpha to true if making a transparency group form x-objects. 148 SkPDFIndirectReference makeFormXObjectFromDevice(bool alpha = false); 149 SkPDFIndirectReference makeFormXObjectFromDevice(SkIRect bbox, bool alpha = false); 150 151 void drawFormXObjectWithMask(SkPDFIndirectReference xObject, 152 SkPDFIndirectReference sMask, 153 SkBlendMode, 154 bool invertClip); 155 156 // If the paint or clip is such that we shouldn't draw anything, this 157 // returns nullptr and does not create a content entry. 158 // setUpContentEntry and finishContentEntry can be used directly, but 159 // the preferred method is to use the ScopedContentEntry helper class. 160 SkDynamicMemoryWStream* setUpContentEntry(const SkClipStack* clipStack, 161 const SkMatrix& matrix, 162 const SkPaint& paint, 163 SkScalar, 164 SkPDFIndirectReference* dst); 165 void finishContentEntry(const SkClipStack*, SkBlendMode, SkPDFIndirectReference, SkPath*); 166 bool isContentEmpty(); 167 168 void internalDrawGlyphRun(const SkGlyphRun& glyphRun, SkPoint offset, const SkPaint& runPaint); 169 void drawGlyphRunAsPath(const SkGlyphRun& glyphRun, SkPoint offset, const SkPaint& runPaint); 170 171 void internalDrawImageRect(SkKeyedImage, 172 const SkRect* src, 173 const SkRect& dst, 174 const SkPaint&, 175 const SkMatrix& canvasTransformationMatrix); 176 177 void internalDrawPath(const SkClipStack&, 178 const SkMatrix&, 179 const SkPath&, 180 const SkPaint&, 181 bool pathIsMutable); 182 183 void internalDrawPathWithFilter(const SkClipStack& clipStack, 184 const SkMatrix& ctm, 185 const SkPath& origPath, 186 const SkPaint& paint); 187 188 bool handleInversePath(const SkPath& origPath, const SkPaint& paint, bool pathIsMutable); 189 190 void clearMaskOnGraphicState(SkDynamicMemoryWStream*); 191 void setGraphicState(SkPDFIndirectReference gs, SkDynamicMemoryWStream*); 192 void drawFormXObject(SkPDFIndirectReference xObject, SkDynamicMemoryWStream*); 193 hasEmptyClip()194 bool hasEmptyClip() const { return this->cs().isEmpty(this->bounds()); } 195 196 void reset(); 197 198 typedef SkClipStackDevice INHERITED; 199 }; 200 201 #endif 202