blob: 7a3e7bb7f1ddf28390d1a2599240c6383423c092 [file] [log] [blame]
vandebo@chromium.org9b49dc02010-10-20 22:23:29 +00001/*
vandebo@chromium.org2a22e102011-01-25 21:01:34 +00002 * Copyright (C) 2011 Google Inc.
vandebo@chromium.org9b49dc02010-10-20 22:23:29 +00003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef SkPDFDevice_DEFINED
18#define SkPDFDevice_DEFINED
19
vandebo@chromium.orgb069c8c2011-05-24 17:19:38 +000020#include "SkCanvas.h"
vandebo@chromium.org9b49dc02010-10-20 22:23:29 +000021#include "SkDevice.h"
vandebo@chromium.orga5180862010-10-26 19:48:49 +000022#include "SkPaint.h"
23#include "SkPath.h"
vandebo@chromium.org9fbdf872011-05-09 07:55:58 +000024#include "SkRefCnt.h"
25#include "SkStream.h"
26#include "SkTScopedPtr.h"
vandebo@chromium.org9b49dc02010-10-20 22:23:29 +000027
28class SkPDFArray;
29class SkPDFDevice;
30class SkPDFDict;
vandebo@chromium.org28be72b2010-11-11 21:37:00 +000031class SkPDFFont;
vandebo@chromium.org6112c212011-05-13 03:50:38 +000032class SkPDFFormXObject;
vandebo@chromium.org9b49dc02010-10-20 22:23:29 +000033class SkPDFGraphicState;
34class SkPDFObject;
vandebo@chromium.orgda912d62011-03-08 18:31:02 +000035class SkPDFShader;
vandebo@chromium.org9b49dc02010-10-20 22:23:29 +000036class SkPDFStream;
37
vandebo@chromium.org9fbdf872011-05-09 07:55:58 +000038// Private classes.
39struct ContentEntry;
40struct GraphicStateEntry;
41
vandebo@chromium.org9b49dc02010-10-20 22:23:29 +000042/** \class SkPDFDevice
43
44 The drawing context for the PDF backend.
45*/
46class SkPDFDevice : public SkDevice {
47public:
48 /** Create a PDF drawing context with the given width and height.
49 * 72 points/in means letter paper is 612x792.
ctguil@chromium.org15261292011-04-29 17:54:16 +000050 * @param pageSize Page size in points.
51 * @param contentSize The content size of the page in points. This will be
52 * combined with the initial transform to determine the drawing area
53 * (as reported by the width and height methods). Anything outside
54 * of the drawing area will be clipped.
vandebo@chromium.org75f97e42011-04-11 23:24:18 +000055 * @param initialTransform The initial transform to apply to the page.
56 * This may be useful to, for example, move the origin in and
57 * over a bit to account for a margin, scale the canvas,
58 * or apply a rotation. Note1: the SkPDFDevice also applies
59 * a scale+translate transform to move the origin from the
60 * bottom left (PDF default) to the top left. Note2: drawDevice
61 * (used by layer restore) draws the device after this initial
reed@google.comcde92112011-07-06 20:00:52 +000062 * transform is applied, so the PDF device does an
vandebo@chromium.org75f97e42011-04-11 23:24:18 +000063 * inverse scale+translate to accommodate the one that SkPDFDevice
64 * always does.
vandebo@chromium.org9b49dc02010-10-20 22:23:29 +000065 */
vandebo@chromium.orgbe2048a2011-05-02 15:24:01 +000066 // TODO(vandebo) The sizes should be SkSize and not SkISize.
ctguil@chromium.org15261292011-04-29 17:54:16 +000067 SK_API SkPDFDevice(const SkISize& pageSize, const SkISize& contentSize,
68 const SkMatrix& initialTransform);
69 SK_API virtual ~SkPDFDevice();
vandebo@chromium.org9b49dc02010-10-20 22:23:29 +000070
vandebo@chromium.org35fc62b2010-10-26 19:47:30 +000071 virtual uint32_t getDeviceCapabilities() { return kVector_Capability; }
72
vandebo@chromium.org77bcaa32011-04-15 20:57:37 +000073 virtual void clear(SkColor color);
74
reed@android.comf2b98d62010-12-20 18:26:13 +000075 virtual bool readPixels(const SkIRect& srcRect, SkBitmap* bitmap) {
76 return false;
77 }
78
vandebo@chromium.org9b49dc02010-10-20 22:23:29 +000079 /** These are called inside the per-device-layer loop for each draw call.
80 When these are called, we have already applied any saveLayer operations,
81 and are handling any looping from the paint, and any effects from the
82 DrawFilter.
83 */
84 virtual void drawPaint(const SkDraw&, const SkPaint& paint);
85 virtual void drawPoints(const SkDraw&, SkCanvas::PointMode mode,
86 size_t count, const SkPoint[],
87 const SkPaint& paint);
88 virtual void drawRect(const SkDraw&, const SkRect& r, const SkPaint& paint);
vandebo@chromium.orgff390322011-05-17 18:58:44 +000089 virtual void drawPath(const SkDraw&, const SkPath& origpath,
vandebo@chromium.org02cc5aa2011-01-25 22:06:29 +000090 const SkPaint& paint, const SkMatrix* prePathMatrix,
91 bool pathIsMutable);
vandebo@chromium.org9b49dc02010-10-20 22:23:29 +000092 virtual void drawBitmap(const SkDraw&, const SkBitmap& bitmap,
reed@android.comf2b98d62010-12-20 18:26:13 +000093 const SkIRect* srcRectOrNull,
vandebo@chromium.org9b49dc02010-10-20 22:23:29 +000094 const SkMatrix& matrix, const SkPaint& paint);
95 virtual void drawSprite(const SkDraw&, const SkBitmap& bitmap, int x, int y,
96 const SkPaint& paint);
97 virtual void drawText(const SkDraw&, const void* text, size_t len,
98 SkScalar x, SkScalar y, const SkPaint& paint);
99 virtual void drawPosText(const SkDraw&, const void* text, size_t len,
100 const SkScalar pos[], SkScalar constY,
101 int scalarsPerPos, const SkPaint& paint);
102 virtual void drawTextOnPath(const SkDraw&, const void* text, size_t len,
103 const SkPath& path, const SkMatrix* matrix,
104 const SkPaint& paint);
105 virtual void drawVertices(const SkDraw&, SkCanvas::VertexMode,
106 int vertexCount, const SkPoint verts[],
107 const SkPoint texs[], const SkColor colors[],
108 SkXfermode* xmode, const uint16_t indices[],
109 int indexCount, const SkPaint& paint);
110 virtual void drawDevice(const SkDraw&, SkDevice*, int x, int y,
111 const SkPaint&);
112
ctguil@chromium.org8dcf74f2011-07-12 21:56:27 +0000113 enum DrawingArea {
114 kContent_DrawingArea, // Drawing area for the page content.
115 kMargin_DrawingArea, // Drawing area for the margin content.
116 };
117
118 /** Sets the drawing area for the device. Subsequent draw calls are directed
119 * to the specific drawing area (margin or content). The default drawing
120 * area is the content drawing area.
121 */
122 void setDrawingArea(DrawingArea drawingArea);
123
vandebo@chromium.org9b49dc02010-10-20 22:23:29 +0000124 // PDF specific methods.
125
reed@google.com1feb3302011-07-20 18:43:19 +0000126 /** Returns the resource dictionary for this device.
vandebo@chromium.org9b49dc02010-10-20 22:23:29 +0000127 */
reed@google.com1feb3302011-07-20 18:43:19 +0000128 SK_API SkPDFDict* getResourceDict();
vandebo@chromium.org9b49dc02010-10-20 22:23:29 +0000129
vandebo@chromium.orga5180862010-10-26 19:48:49 +0000130 /** Get the list of resources (PDF objects) used on this page.
131 * @param resourceList A list to append the resources to.
vandebo@chromium.org9b49dc02010-10-20 22:23:29 +0000132 */
vandebo@chromium.org3509f052011-05-30 20:52:33 +0000133 SK_API void getResources(SkTDArray<SkPDFObject*>* resourceList) const;
vandebo@chromium.org9b49dc02010-10-20 22:23:29 +0000134
vandebo@chromium.orgf0ec2662011-05-29 05:55:42 +0000135 /** Get the fonts used on this device.
136 */
vandebo@chromium.org3509f052011-05-30 20:52:33 +0000137 SK_API const SkTDArray<SkPDFFont*>& getFontResources() const;
vandebo@chromium.orgf0ec2662011-05-29 05:55:42 +0000138
vandebo@chromium.org9b49dc02010-10-20 22:23:29 +0000139 /** Returns the media box for this device.
140 */
vandebo@chromium.org3509f052011-05-30 20:52:33 +0000141 SK_API SkRefPtr<SkPDFArray> getMediaBox() const;
vandebo@chromium.org9b49dc02010-10-20 22:23:29 +0000142
vandebo@chromium.orgc2a9b7f2011-02-24 23:22:30 +0000143 /** Returns a SkStream with the page contents. The caller is responsible
144 for a reference to the returned value.
reed@google.com5667afc2011-06-27 14:42:15 +0000145 DEPRECATED: use copyContentToData()
vandebo@chromium.org9b49dc02010-10-20 22:23:29 +0000146 */
vandebo@chromium.org3509f052011-05-30 20:52:33 +0000147 SK_API SkStream* content() const;
vandebo@chromium.org9b49dc02010-10-20 22:23:29 +0000148
reed@google.com5667afc2011-06-27 14:42:15 +0000149 /** Returns a SkStream with the page contents. The caller is responsible
150 * for calling data->unref() when it is finished.
151 */
152 SK_API SkData* copyContentToData() const;
153
vandebo@chromium.org3509f052011-05-30 20:52:33 +0000154 SK_API const SkMatrix& initialTransform() const {
155 return fInitialTransform;
156 }
vandebo@chromium.org61d26782011-05-24 23:02:07 +0000157
vandebo@chromium.org9b49dc02010-10-20 22:23:29 +0000158private:
vandebo@chromium.orgb069c8c2011-05-24 17:19:38 +0000159 // TODO(vandebo) push most of SkPDFDevice's state into a core object in
160 // order to get the right access levels without using friend.
vandebo@chromium.org13d14a92011-05-24 23:12:41 +0000161 friend class ScopedContentEntry;
vandebo@chromium.orga0c7edb2011-05-09 07:58:08 +0000162
ctguil@chromium.org15261292011-04-29 17:54:16 +0000163 SkISize fPageSize;
vandebo@chromium.org9fbdf872011-05-09 07:55:58 +0000164 SkISize fContentSize;
vandebo@chromium.org75f97e42011-04-11 23:24:18 +0000165 SkMatrix fInitialTransform;
vandebo@chromium.org9fbdf872011-05-09 07:55:58 +0000166 SkClipStack fExistingClipStack;
167 SkRegion fExistingClipRegion;
vandebo@chromium.org9b49dc02010-10-20 22:23:29 +0000168 SkRefPtr<SkPDFDict> fResourceDict;
169
vandebo@chromium.org9b49dc02010-10-20 22:23:29 +0000170 SkTDArray<SkPDFGraphicState*> fGraphicStateResources;
171 SkTDArray<SkPDFObject*> fXObjectResources;
vandebo@chromium.org28be72b2010-11-11 21:37:00 +0000172 SkTDArray<SkPDFFont*> fFontResources;
vandebo@chromium.org421d6442011-07-20 17:39:01 +0000173 SkTDArray<SkPDFObject*> fShaderResources;
vandebo@chromium.org9b49dc02010-10-20 22:23:29 +0000174
vandebo@chromium.org9fbdf872011-05-09 07:55:58 +0000175 SkTScopedPtr<ContentEntry> fContentEntries;
vandebo@chromium.orgb069c8c2011-05-24 17:19:38 +0000176 ContentEntry* fLastContentEntry;
ctguil@chromium.org8dcf74f2011-07-12 21:56:27 +0000177 SkTScopedPtr<ContentEntry> fMarginContentEntries;
178 ContentEntry* fLastMarginContentEntry;
179 DrawingArea fDrawingArea;
180
181 // Accessor and setter functions based on the current DrawingArea.
182 SkTScopedPtr<ContentEntry>& getContentEntries();
183 ContentEntry* getLastContentEntry();
184 void setLastContentEntry(ContentEntry* contentEntry);
vandebo@chromium.org9b49dc02010-10-20 22:23:29 +0000185
vandebo@chromium.orga0c7edb2011-05-09 07:58:08 +0000186 SkPDFDevice(const SkISize& layerSize, const SkClipStack& existingClipStack,
187 const SkRegion& existingClipRegion);
188
bsalomon@google.come97f0852011-06-17 13:10:25 +0000189 // override from SkDevice
190 virtual SkDevice* onCreateCompatibleDevice(SkBitmap::Config config,
191 int width, int height,
192 bool isOpaque,
193 Usage usage);
194
vandebo@chromium.org77bcaa32011-04-15 20:57:37 +0000195 void init();
196 void cleanUp();
vandebo@chromium.org6112c212011-05-13 03:50:38 +0000197 void createFormXObjectFromDevice(SkRefPtr<SkPDFFormXObject>* xobject);
vandebo@chromium.org9fbdf872011-05-09 07:55:58 +0000198
vandebo@chromium.org466f3d62011-05-18 23:06:29 +0000199 // Clear the passed clip from all existing content entries.
200 void clearClipFromContent(const SkClipStack* clipStack,
201 const SkRegion& clipRegion);
vandebo@chromium.org481aef62011-05-24 16:39:05 +0000202 void drawFormXObjectWithClip(SkPDFFormXObject* form,
203 const SkClipStack* clipStack,
204 const SkRegion& clipRegion,
205 bool invertClip);
vandebo@chromium.org466f3d62011-05-18 23:06:29 +0000206
vandebo@chromium.orgb069c8c2011-05-24 17:19:38 +0000207 // If the paint or clip is such that we shouldn't draw anything, this
208 // returns NULL and does not create a content entry.
209 // setUpContentEntry and finishContentEntry can be used directly, but
vandebo@chromium.org13d14a92011-05-24 23:12:41 +0000210 // the preferred method is to use the ScopedContentEntry helper class.
vandebo@chromium.orgb069c8c2011-05-24 17:19:38 +0000211 ContentEntry* setUpContentEntry(const SkClipStack* clipStack,
212 const SkRegion& clipRegion,
213 const SkMatrix& matrix,
214 const SkPaint& paint,
215 bool hasText,
216 SkRefPtr<SkPDFFormXObject>* dst);
217 void finishContentEntry(SkXfermode::Mode xfermode,
218 SkPDFFormXObject* dst);
vandebo@chromium.org481aef62011-05-24 16:39:05 +0000219 bool isContentEmpty();
220
vandebo@chromium.org9fbdf872011-05-09 07:55:58 +0000221 void populateGraphicStateEntryFromPaint(const SkMatrix& matrix,
222 const SkClipStack& clipStack,
223 const SkRegion& clipRegion,
224 const SkPaint& paint,
225 bool hasText,
226 GraphicStateEntry* entry);
vandebo@chromium.org6112c212011-05-13 03:50:38 +0000227 int addGraphicStateResource(SkPDFGraphicState* gs);
vandebo@chromium.org9fbdf872011-05-09 07:55:58 +0000228
vandebo@chromium.orgb069c8c2011-05-24 17:19:38 +0000229 void updateFont(const SkPaint& paint, uint16_t glyphID,
230 ContentEntry* contentEntry);
ctguil@chromium.org9db86bb2011-03-04 21:43:27 +0000231 int getFontResourceIndex(SkTypeface* typeface, uint16_t glyphID);
vandebo@chromium.org9b49dc02010-10-20 22:23:29 +0000232
vandebo@chromium.orgb069c8c2011-05-24 17:19:38 +0000233 void internalDrawPaint(const SkPaint& paint, ContentEntry* contentEntry);
vandebo@chromium.org9fbdf872011-05-09 07:55:58 +0000234 void internalDrawBitmap(const SkMatrix& matrix,
vandebo@chromium.org78dad542011-05-11 18:46:03 +0000235 const SkClipStack* clipStack,
vandebo@chromium.org9fbdf872011-05-09 07:55:58 +0000236 const SkRegion& clipRegion,
237 const SkBitmap& bitmap,
238 const SkIRect* srcRect,
239 const SkPaint& paint);
240
ctguil@chromium.org8dcf74f2011-07-12 21:56:27 +0000241 /** Helper method for copyContentToData. It is responsible for copying the
242 * list of content entries |entry| to |data|.
243 */
244 void copyContentEntriesToData(ContentEntry* entry, SkWStream* data) const;
245
vandebo@chromium.org9fbdf872011-05-09 07:55:58 +0000246 // Disable the default copy and assign implementation.
247 SkPDFDevice(const SkPDFDevice&);
248 void operator=(const SkPDFDevice&);
vandebo@chromium.org9b49dc02010-10-20 22:23:29 +0000249};
250
251#endif