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 SkImageFilterCache* getImageFilterCache() override; 122 123 private: 124 // TODO(vandebo): push most of SkPDFDevice's state into a core object in 125 // order to get the right access levels without using friend. 126 friend class ScopedContentEntry; 127 128 SkMatrix fInitialTransform; 129 130 SkTHashSet<SkPDFIndirectReference> fGraphicStateResources; 131 SkTHashSet<SkPDFIndirectReference> fXObjectResources; 132 SkTHashSet<SkPDFIndirectReference> fShaderResources; 133 SkTHashSet<SkPDFIndirectReference> fFontResources; 134 int fNodeId; 135 136 SkDynamicMemoryWStream fContent; 137 SkDynamicMemoryWStream fContentBuffer; 138 bool fNeedsExtraSave = false; 139 SkPDFGraphicStackState fActiveStackState; 140 SkPDFDocument* fDocument; 141 142 //////////////////////////////////////////////////////////////////////////// 143 144 SkBaseDevice* onCreateDevice(const CreateInfo&, const SkPaint*) override; 145 146 // Set alpha to true if making a transparency group form x-objects. 147 SkPDFIndirectReference makeFormXObjectFromDevice(bool alpha = false); 148 SkPDFIndirectReference makeFormXObjectFromDevice(SkIRect bbox, bool alpha = false); 149 150 void drawFormXObjectWithMask(SkPDFIndirectReference xObject, 151 SkPDFIndirectReference sMask, 152 SkBlendMode, 153 bool invertClip); 154 155 // If the paint or clip is such that we shouldn't draw anything, this 156 // returns nullptr and does not create a content entry. 157 // setUpContentEntry and finishContentEntry can be used directly, but 158 // the preferred method is to use the ScopedContentEntry helper class. 159 SkDynamicMemoryWStream* setUpContentEntry(const SkClipStack* clipStack, 160 const SkMatrix& matrix, 161 const SkPaint& paint, 162 SkScalar, 163 SkPDFIndirectReference* dst); 164 void finishContentEntry(const SkClipStack*, SkBlendMode, SkPDFIndirectReference, SkPath*); 165 bool isContentEmpty(); 166 167 void internalDrawGlyphRun(const SkGlyphRun& glyphRun, SkPoint offset, const SkPaint& runPaint); 168 void drawGlyphRunAsPath(const SkGlyphRun& glyphRun, SkPoint offset, const SkPaint& runPaint); 169 170 void internalDrawImageRect(SkKeyedImage, 171 const SkRect* src, 172 const SkRect& dst, 173 const SkPaint&, 174 const SkMatrix& canvasTransformationMatrix); 175 176 void internalDrawPath(const SkClipStack&, 177 const SkMatrix&, 178 const SkPath&, 179 const SkPaint&, 180 bool pathIsMutable); 181 182 void internalDrawPathWithFilter(const SkClipStack& clipStack, 183 const SkMatrix& ctm, 184 const SkPath& origPath, 185 const SkPaint& paint); 186 187 bool handleInversePath(const SkPath& origPath, const SkPaint& paint, bool pathIsMutable); 188 189 void clearMaskOnGraphicState(SkDynamicMemoryWStream*); 190 void setGraphicState(SkPDFIndirectReference gs, SkDynamicMemoryWStream*); 191 void drawFormXObject(SkPDFIndirectReference xObject, SkDynamicMemoryWStream*); 192 hasEmptyClip()193 bool hasEmptyClip() const { return this->cs().isEmpty(this->bounds()); } 194 195 void reset(); 196 197 typedef SkClipStackDevice INHERITED; 198 }; 199 200 #endif 201