blob: 18be58de437ada291cd853a488c5dd7a89874c31 [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001
vandebo@chromium.org9b49dc02010-10-20 22:23:29 +00002/*
epoger@google.comec3ed6a2011-07-28 14:26:00 +00003 * Copyright 2011 Google Inc.
vandebo@chromium.org9b49dc02010-10-20 22:23:29 +00004 *
epoger@google.comec3ed6a2011-07-28 14:26:00 +00005 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
vandebo@chromium.org9b49dc02010-10-20 22:23:29 +00007 */
8
epoger@google.comec3ed6a2011-07-28 14:26:00 +00009
vandebo@chromium.org9b49dc02010-10-20 22:23:29 +000010#ifndef SkPDFDevice_DEFINED
11#define SkPDFDevice_DEFINED
12
reed89443ab2014-06-27 11:34:19 -070013#include "SkDevice.h"
commit-bot@chromium.org5e009892013-10-14 13:42:12 +000014#include "SkBitmap.h"
vandebo@chromium.orgb069c8c2011-05-24 17:19:38 +000015#include "SkCanvas.h"
vandebo@chromium.orga5180862010-10-26 19:48:49 +000016#include "SkPaint.h"
17#include "SkPath.h"
commit-bot@chromium.org608ea652013-10-03 19:29:21 +000018#include "SkPicture.h"
vandebo@chromium.org238be8c2012-07-13 20:06:02 +000019#include "SkRect.h"
vandebo@chromium.org9fbdf872011-05-09 07:55:58 +000020#include "SkRefCnt.h"
21#include "SkStream.h"
epoger@google.comb58772f2013-03-08 09:09:10 +000022#include "SkTDArray.h"
commit-bot@chromium.orge0294402013-08-29 22:14:04 +000023#include "SkTemplates.h"
vandebo@chromium.org9b49dc02010-10-20 22:23:29 +000024
25class SkPDFArray;
halcanarya1f1ee92015-02-20 06:17:26 -080026class SkPDFCanon;
vandebo@chromium.org9b49dc02010-10-20 22:23:29 +000027class SkPDFDevice;
28class SkPDFDict;
vandebo@chromium.org28be72b2010-11-11 21:37:00 +000029class SkPDFFont;
vandebo@chromium.org6112c212011-05-13 03:50:38 +000030class SkPDFFormXObject;
vandebo@chromium.org98594282011-07-25 22:34:12 +000031class SkPDFGlyphSetMap;
vandebo@chromium.org9b49dc02010-10-20 22:23:29 +000032class SkPDFGraphicState;
33class SkPDFObject;
vandebo@chromium.orgda912d62011-03-08 18:31:02 +000034class SkPDFShader;
vandebo@chromium.org9b49dc02010-10-20 22:23:29 +000035class SkPDFStream;
scroggo@google.coma8e33a92013-11-08 18:02:53 +000036class SkRRect;
vandebo@chromium.org9b49dc02010-10-20 22:23:29 +000037
vandebo@chromium.org9fbdf872011-05-09 07:55:58 +000038// Private classes.
39struct ContentEntry;
40struct GraphicStateEntry;
epoger@google.comb58772f2013-03-08 09:09:10 +000041struct NamedDestination;
vandebo@chromium.org9fbdf872011-05-09 07:55:58 +000042
vandebo@chromium.org9b49dc02010-10-20 22:23:29 +000043/** \class SkPDFDevice
44
45 The drawing context for the PDF backend.
46*/
reed89443ab2014-06-27 11:34:19 -070047class SkPDFDevice : public SkBaseDevice {
vandebo@chromium.org9b49dc02010-10-20 22:23:29 +000048public:
halcanarya1f1ee92015-02-20 06:17:26 -080049 /** Create a PDF drawing context. SkPDFDevice applies a
50 * scale-and-translate transform to move the origin from the
51 * bottom left (PDF default) to the top left (Skia default).
52 * @param pageSize Page size in point units.
53 * 1 point == 127/360 mm == 1/72 inch
54 * @param rasterDpi the DPI at which features without native PDF
55 * support will be rasterized (e.g. draw image with
56 * perspective, draw text with perspective, ...). A
57 * larger DPI would create a PDF that reflects the
58 * original intent with better fidelity, but it can make
59 * for larger PDF files too, which would use more memory
60 * while rendering, and it would be slower to be processed
61 * or sent online or to printer. A good choice is
62 * SK_ScalarDefaultRasterDPI(72.0f).
63 * @param SkPDFCanon. Should be non-null, and shared by all
64 * devices in a document.
vandebo@chromium.org9b49dc02010-10-20 22:23:29 +000065 */
halcanarya1f1ee92015-02-20 06:17:26 -080066 static SkPDFDevice* Create(SkISize pageSize,
67 SkScalar rasterDpi,
68 SkPDFCanon* canon) {
69 return SkNEW_ARGS(SkPDFDevice, (pageSize, rasterDpi, canon, true));
70 }
71
72 /** Create a PDF drawing context without fipping the y-axis. */
73 static SkPDFDevice* CreateUnflipped(SkISize pageSize,
74 SkScalar rasterDpi,
75 SkPDFCanon* canon) {
76 return SkNEW_ARGS(SkPDFDevice, (pageSize, rasterDpi, canon, false));
77 }
78
79 virtual ~SkPDFDevice();
vandebo@chromium.org9b49dc02010-10-20 22:23:29 +000080
vandebo@chromium.org9b49dc02010-10-20 22:23:29 +000081 /** These are called inside the per-device-layer loop for each draw call.
82 When these are called, we have already applied any saveLayer operations,
83 and are handling any looping from the paint, and any effects from the
84 DrawFilter.
85 */
mtklein36352bf2015-03-25 18:17:31 -070086 void drawPaint(const SkDraw&, const SkPaint& paint) override;
tfarinafa4f6cb2014-12-21 10:27:07 -080087 void drawPoints(const SkDraw&, SkCanvas::PointMode mode,
88 size_t count, const SkPoint[],
mtklein36352bf2015-03-25 18:17:31 -070089 const SkPaint& paint) override;
90 void drawRect(const SkDraw&, const SkRect& r, const SkPaint& paint) override;
91 void drawOval(const SkDraw&, const SkRect& oval, const SkPaint& paint) override;
92 void drawRRect(const SkDraw&, const SkRRect& rr, const SkPaint& paint) override;
tfarinafa4f6cb2014-12-21 10:27:07 -080093 void drawPath(const SkDraw&, const SkPath& origpath,
94 const SkPaint& paint, const SkMatrix* prePathMatrix,
mtklein36352bf2015-03-25 18:17:31 -070095 bool pathIsMutable) override;
tfarinafa4f6cb2014-12-21 10:27:07 -080096 void drawBitmapRect(const SkDraw& draw, const SkBitmap& bitmap,
97 const SkRect* src, const SkRect& dst,
98 const SkPaint& paint,
mtklein36352bf2015-03-25 18:17:31 -070099 SkCanvas::DrawBitmapRectFlags flags) override;
tfarinafa4f6cb2014-12-21 10:27:07 -0800100 void drawBitmap(const SkDraw&, const SkBitmap& bitmap,
mtklein36352bf2015-03-25 18:17:31 -0700101 const SkMatrix& matrix, const SkPaint&) override;
tfarinafa4f6cb2014-12-21 10:27:07 -0800102 void drawSprite(const SkDraw&, const SkBitmap& bitmap, int x, int y,
mtklein36352bf2015-03-25 18:17:31 -0700103 const SkPaint& paint) override;
tfarinafa4f6cb2014-12-21 10:27:07 -0800104 void drawText(const SkDraw&, const void* text, size_t len,
mtklein36352bf2015-03-25 18:17:31 -0700105 SkScalar x, SkScalar y, const SkPaint&) override;
tfarinafa4f6cb2014-12-21 10:27:07 -0800106 void drawPosText(const SkDraw&, const void* text, size_t len,
107 const SkScalar pos[], int scalarsPerPos,
mtklein36352bf2015-03-25 18:17:31 -0700108 const SkPoint& offset, const SkPaint&) override;
tfarinafa4f6cb2014-12-21 10:27:07 -0800109 void drawVertices(const SkDraw&, SkCanvas::VertexMode,
110 int vertexCount, const SkPoint verts[],
111 const SkPoint texs[], const SkColor colors[],
112 SkXfermode* xmode, const uint16_t indices[],
mtklein36352bf2015-03-25 18:17:31 -0700113 int indexCount, const SkPaint& paint) override;
tfarinafa4f6cb2014-12-21 10:27:07 -0800114 void drawDevice(const SkDraw&, SkBaseDevice*, int x, int y,
mtklein36352bf2015-03-25 18:17:31 -0700115 const SkPaint&) override;
vandebo@chromium.org9b49dc02010-10-20 22:23:29 +0000116
mtklein36352bf2015-03-25 18:17:31 -0700117 void onAttachToCanvas(SkCanvas* canvas) override;
118 void onDetachFromCanvas() override;
119 SkImageInfo imageInfo() const override;
robertphillips@google.com40a1ae42012-07-13 15:36:15 +0000120
ctguil@chromium.org8dcf74f2011-07-12 21:56:27 +0000121 enum DrawingArea {
ctguil@chromium.org9510ccc2011-07-27 00:10:51 +0000122 kContent_DrawingArea, // Drawing area for the page content.
123 kMargin_DrawingArea, // Drawing area for the margin content.
ctguil@chromium.org8dcf74f2011-07-12 21:56:27 +0000124 };
125
126 /** Sets the drawing area for the device. Subsequent draw calls are directed
ctguil@chromium.org769fa6a2011-08-20 00:36:18 +0000127 * to the specific drawing area (margin or content). The default drawing
ctguil@chromium.org8dcf74f2011-07-12 21:56:27 +0000128 * area is the content drawing area.
ctguil@chromium.org9510ccc2011-07-27 00:10:51 +0000129 *
130 * Currently if margin content is drawn and then a complex (for PDF) xfer
131 * mode is used, like SrcIn, Clear, etc, the margin content will get
132 * clipped. A simple way to avoid the bug is to always draw the margin
133 * content last.
ctguil@chromium.org8dcf74f2011-07-12 21:56:27 +0000134 */
halcanary4e4e8162015-02-25 08:59:48 -0800135 void setDrawingArea(DrawingArea drawingArea);
ctguil@chromium.org8dcf74f2011-07-12 21:56:27 +0000136
vandebo@chromium.org9b49dc02010-10-20 22:23:29 +0000137 // PDF specific methods.
138
halcanary6d622702015-03-25 08:45:42 -0700139 /** Create the resource dictionary for this device.
vandebo@chromium.org9b49dc02010-10-20 22:23:29 +0000140 */
halcanary2b861552015-04-09 13:27:40 -0700141 SkPDFDict* createResourceDict() const;
vandebo@chromium.org9b49dc02010-10-20 22:23:29 +0000142
vandebo@chromium.orgf0ec2662011-05-29 05:55:42 +0000143 /** Get the fonts used on this device.
144 */
halcanary4e4e8162015-02-25 08:59:48 -0800145 const SkTDArray<SkPDFFont*>& getFontResources() const;
vandebo@chromium.orgf0ec2662011-05-29 05:55:42 +0000146
epoger@google.comb58772f2013-03-08 09:09:10 +0000147 /** Add our named destinations to the supplied dictionary.
148 * @param dict Dictionary to add destinations to.
149 * @param page The PDF object representing the page for this device.
150 */
halcanary6d622702015-03-25 08:45:42 -0700151 void appendDestinations(SkPDFDict* dict, SkPDFObject* page) const;
epoger@google.comb58772f2013-03-08 09:09:10 +0000152
reed@google.com2a006c12012-09-19 17:05:55 +0000153 /** Returns a copy of the media box for this device. The caller is required
154 * to unref() this when it is finished.
vandebo@chromium.org9b49dc02010-10-20 22:23:29 +0000155 */
halcanary4e4e8162015-02-25 08:59:48 -0800156 SkPDFArray* copyMediaBox() const;
vandebo@chromium.org9b49dc02010-10-20 22:23:29 +0000157
reed@google.com2a006c12012-09-19 17:05:55 +0000158 /** Get the annotations from this page, or NULL if there are none.
vandebo@chromium.org238be8c2012-07-13 20:06:02 +0000159 */
halcanary4e4e8162015-02-25 08:59:48 -0800160 SkPDFArray* getAnnotations() const { return fAnnotations; }
vandebo@chromium.org238be8c2012-07-13 20:06:02 +0000161
vandebo@chromium.orgc2a9b7f2011-02-24 23:22:30 +0000162 /** Returns a SkStream with the page contents. The caller is responsible
halcanary4e4e8162015-02-25 08:59:48 -0800163 * for a deleting the returned value.
vandebo@chromium.org9b49dc02010-10-20 22:23:29 +0000164 */
halcanary4e4e8162015-02-25 08:59:48 -0800165 SkStreamAsset* content() const;
vandebo@chromium.org9b49dc02010-10-20 22:23:29 +0000166
halcanary334fcbc2015-02-24 12:56:16 -0800167 /** Writes the page contents to the stream. */
halcanary4e4e8162015-02-25 08:59:48 -0800168 void writeContent(SkWStream*) const;
vandebo@chromium.org98594282011-07-25 22:34:12 +0000169
halcanary4e4e8162015-02-25 08:59:48 -0800170 const SkMatrix& initialTransform() const {
vandebo@chromium.org3509f052011-05-30 20:52:33 +0000171 return fInitialTransform;
172 }
vandebo@chromium.org61d26782011-05-24 23:02:07 +0000173
vandebo@chromium.org98594282011-07-25 22:34:12 +0000174 /** Returns a SkPDFGlyphSetMap which represents glyph usage of every font
175 * that shows on this device.
176 */
177 const SkPDFGlyphSetMap& getFontGlyphUsage() const {
178 return *(fFontGlyphUsage.get());
179 }
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000180
halcanary26b5d152015-03-25 08:38:03 -0700181#ifdef SK_DEBUG
182 SkPDFCanon* getCanon() const { return fCanon; }
183#endif // SK_DEBUG
184
edisonn@google.com73a7ea32013-11-11 20:55:15 +0000185protected:
mtklein36352bf2015-03-25 18:17:31 -0700186 const SkBitmap& onAccessBitmap() override {
reed89443ab2014-06-27 11:34:19 -0700187 return fLegacyBitmap;
188 }
189
mtklein36352bf2015-03-25 18:17:31 -0700190 SkSurface* newSurface(const SkImageInfo&, const SkSurfaceProps&) override;
edisonn@google.com73a7ea32013-11-11 20:55:15 +0000191
vandebo@chromium.org9b49dc02010-10-20 22:23:29 +0000192private:
ctguil@chromium.org769fa6a2011-08-20 00:36:18 +0000193 // TODO(vandebo): push most of SkPDFDevice's state into a core object in
vandebo@chromium.orgb069c8c2011-05-24 17:19:38 +0000194 // order to get the right access levels without using friend.
vandebo@chromium.org13d14a92011-05-24 23:12:41 +0000195 friend class ScopedContentEntry;
vandebo@chromium.orga0c7edb2011-05-09 07:58:08 +0000196
ctguil@chromium.org15261292011-04-29 17:54:16 +0000197 SkISize fPageSize;
vandebo@chromium.org9fbdf872011-05-09 07:55:58 +0000198 SkISize fContentSize;
vandebo@chromium.org75f97e42011-04-11 23:24:18 +0000199 SkMatrix fInitialTransform;
vandebo@chromium.org9fbdf872011-05-09 07:55:58 +0000200 SkClipStack fExistingClipStack;
201 SkRegion fExistingClipRegion;
reed@google.com2a006c12012-09-19 17:05:55 +0000202 SkPDFArray* fAnnotations;
epoger@google.comb58772f2013-03-08 09:09:10 +0000203 SkTDArray<NamedDestination*> fNamedDestinations;
vandebo@chromium.org9b49dc02010-10-20 22:23:29 +0000204
halcanarybe27a112015-04-01 13:31:19 -0700205 SkTDArray<SkPDFObject*> fGraphicStateResources;
vandebo@chromium.org9b49dc02010-10-20 22:23:29 +0000206 SkTDArray<SkPDFObject*> fXObjectResources;
vandebo@chromium.org28be72b2010-11-11 21:37:00 +0000207 SkTDArray<SkPDFFont*> fFontResources;
vandebo@chromium.org421d6442011-07-20 17:39:01 +0000208 SkTDArray<SkPDFObject*> fShaderResources;
vandebo@chromium.org9b49dc02010-10-20 22:23:29 +0000209
commit-bot@chromium.orge0294402013-08-29 22:14:04 +0000210 SkAutoTDelete<ContentEntry> fContentEntries;
vandebo@chromium.orgb069c8c2011-05-24 17:19:38 +0000211 ContentEntry* fLastContentEntry;
commit-bot@chromium.orge0294402013-08-29 22:14:04 +0000212 SkAutoTDelete<ContentEntry> fMarginContentEntries;
ctguil@chromium.org8dcf74f2011-07-12 21:56:27 +0000213 ContentEntry* fLastMarginContentEntry;
214 DrawingArea fDrawingArea;
215
robertphillips@google.com40a1ae42012-07-13 15:36:15 +0000216 const SkClipStack* fClipStack;
217
ctguil@chromium.org8dcf74f2011-07-12 21:56:27 +0000218 // Accessor and setter functions based on the current DrawingArea.
commit-bot@chromium.orge0294402013-08-29 22:14:04 +0000219 SkAutoTDelete<ContentEntry>* getContentEntries();
vandebo@chromium.org9b49dc02010-10-20 22:23:29 +0000220
vandebo@chromium.org98594282011-07-25 22:34:12 +0000221 // Glyph ids used for each font on this device.
commit-bot@chromium.orge0294402013-08-29 22:14:04 +0000222 SkAutoTDelete<SkPDFGlyphSetMap> fFontGlyphUsage;
vandebo@chromium.org98594282011-07-25 22:34:12 +0000223
commit-bot@chromium.org8c294902013-10-21 17:14:37 +0000224 SkScalar fRasterDpi;
edisonn@google.comd9dfa182013-04-24 13:01:01 +0000225
reed89443ab2014-06-27 11:34:19 -0700226 SkBitmap fLegacyBitmap;
227
halcanarya1f1ee92015-02-20 06:17:26 -0800228 SkPDFCanon* fCanon; // Owned by SkDocument_PDF
229 ////////////////////////////////////////////////////////////////////////////
230
231 SkPDFDevice(SkISize pageSize,
232 SkScalar rasterDpi,
233 SkPDFCanon* canon,
234 bool flip);
235
236 ContentEntry* getLastContentEntry();
237 void setLastContentEntry(ContentEntry* contentEntry);
vandebo@chromium.orga0c7edb2011-05-09 07:58:08 +0000238
mtklein36352bf2015-03-25 18:17:31 -0700239 SkBaseDevice* onCreateDevice(const CreateInfo&, const SkPaint*) override;
bsalomon@google.come97f0852011-06-17 13:10:25 +0000240
vandebo@chromium.org77bcaa32011-04-15 20:57:37 +0000241 void init();
vandebo@chromium.org98594282011-07-25 22:34:12 +0000242 void cleanUp(bool clearFontUsage);
reed@google.comfc641d02012-09-20 17:52:20 +0000243 SkPDFFormXObject* createFormXObjectFromDevice();
vandebo@chromium.org9fbdf872011-05-09 07:55:58 +0000244
vandebo@chromium.org3b416212013-10-30 20:48:05 +0000245 void drawFormXObjectWithMask(int xObjectIndex,
246 SkPDFFormXObject* mask,
vandebo@chromium.org481aef62011-05-24 16:39:05 +0000247 const SkClipStack* clipStack,
248 const SkRegion& clipRegion,
vandebo@chromium.org3b416212013-10-30 20:48:05 +0000249 SkXfermode::Mode mode,
vandebo@chromium.org481aef62011-05-24 16:39:05 +0000250 bool invertClip);
vandebo@chromium.org466f3d62011-05-18 23:06:29 +0000251
vandebo@chromium.orgb069c8c2011-05-24 17:19:38 +0000252 // If the paint or clip is such that we shouldn't draw anything, this
253 // returns NULL and does not create a content entry.
254 // setUpContentEntry and finishContentEntry can be used directly, but
vandebo@chromium.org13d14a92011-05-24 23:12:41 +0000255 // the preferred method is to use the ScopedContentEntry helper class.
vandebo@chromium.orgb069c8c2011-05-24 17:19:38 +0000256 ContentEntry* setUpContentEntry(const SkClipStack* clipStack,
257 const SkRegion& clipRegion,
258 const SkMatrix& matrix,
259 const SkPaint& paint,
260 bool hasText,
reed@google.comfc641d02012-09-20 17:52:20 +0000261 SkPDFFormXObject** dst);
vandebo@chromium.orgb069c8c2011-05-24 17:19:38 +0000262 void finishContentEntry(SkXfermode::Mode xfermode,
vandebo@chromium.org3b416212013-10-30 20:48:05 +0000263 SkPDFFormXObject* dst,
264 SkPath* shape);
vandebo@chromium.org481aef62011-05-24 16:39:05 +0000265 bool isContentEmpty();
266
vandebo@chromium.org9fbdf872011-05-09 07:55:58 +0000267 void populateGraphicStateEntryFromPaint(const SkMatrix& matrix,
268 const SkClipStack& clipStack,
269 const SkRegion& clipRegion,
270 const SkPaint& paint,
271 bool hasText,
272 GraphicStateEntry* entry);
halcanarybe27a112015-04-01 13:31:19 -0700273 int addGraphicStateResource(SkPDFObject* gs);
vandebo@chromium.org3b416212013-10-30 20:48:05 +0000274 int addXObjectResource(SkPDFObject* xObject);
vandebo@chromium.org9fbdf872011-05-09 07:55:58 +0000275
vandebo@chromium.orgb069c8c2011-05-24 17:19:38 +0000276 void updateFont(const SkPaint& paint, uint16_t glyphID,
277 ContentEntry* contentEntry);
ctguil@chromium.org9db86bb2011-03-04 21:43:27 +0000278 int getFontResourceIndex(SkTypeface* typeface, uint16_t glyphID);
vandebo@chromium.org9b49dc02010-10-20 22:23:29 +0000279
vandebo@chromium.orgb069c8c2011-05-24 17:19:38 +0000280 void internalDrawPaint(const SkPaint& paint, ContentEntry* contentEntry);
vandebo@chromium.org9fbdf872011-05-09 07:55:58 +0000281 void internalDrawBitmap(const SkMatrix& matrix,
vandebo@chromium.org78dad542011-05-11 18:46:03 +0000282 const SkClipStack* clipStack,
vandebo@chromium.org9fbdf872011-05-09 07:55:58 +0000283 const SkRegion& clipRegion,
284 const SkBitmap& bitmap,
285 const SkIRect* srcRect,
286 const SkPaint& paint);
287
ctguil@chromium.org8dcf74f2011-07-12 21:56:27 +0000288 /** Helper method for copyContentToData. It is responsible for copying the
289 * list of content entries |entry| to |data|.
290 */
291 void copyContentEntriesToData(ContentEntry* entry, SkWStream* data) const;
ctguil@chromium.org9510ccc2011-07-27 00:10:51 +0000292
commit-bot@chromium.org92ffe7d2013-07-31 22:54:31 +0000293 bool handleInversePath(const SkDraw& d, const SkPath& origPath,
edisonn@google.coma9ebd162013-10-07 13:22:21 +0000294 const SkPaint& paint, bool pathIsMutable,
295 const SkMatrix* prePathMatrix = NULL);
epoger@google.comb58772f2013-03-08 09:09:10 +0000296 bool handleRectAnnotation(const SkRect& r, const SkMatrix& matrix,
297 const SkPaint& paint);
298 bool handlePointAnnotation(const SkPoint* points, size_t count,
299 const SkMatrix& matrix, const SkPaint& paint);
halcanary438de492015-04-28 06:21:01 -0700300 void addAnnotation(SkPDFDict*);
epoger@google.comb58772f2013-03-08 09:09:10 +0000301 void handleLinkToURL(SkData* urlData, const SkRect& r,
302 const SkMatrix& matrix);
303 void handleLinkToNamedDest(SkData* nameData, const SkRect& r,
304 const SkMatrix& matrix);
305 void defineNamedDestination(SkData* nameData, const SkPoint& point,
306 const SkMatrix& matrix);
vandebo@chromium.org238be8c2012-07-13 20:06:02 +0000307
reed89443ab2014-06-27 11:34:19 -0700308 typedef SkBaseDevice INHERITED;
commit-bot@chromium.org5e009892013-10-14 13:42:12 +0000309
310 // TODO(edisonn): Only SkDocument_PDF and SkPDFImageShader should be able to create
311 // an SkPDFDevice
312 //friend class SkDocument_PDF;
313 //friend class SkPDFImageShader;
vandebo@chromium.org9b49dc02010-10-20 22:23:29 +0000314};
315
316#endif