• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2011 Google Inc.
3  *
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 
20 #include "SkCanvas.h"
21 #include "SkDevice.h"
22 #include "SkPaint.h"
23 #include "SkPath.h"
24 #include "SkRefCnt.h"
25 #include "SkStream.h"
26 #include "SkTScopedPtr.h"
27 
28 class SkPDFArray;
29 class SkPDFDevice;
30 class SkPDFDict;
31 class SkPDFFont;
32 class SkPDFFormXObject;
33 class SkPDFGraphicState;
34 class SkPDFObject;
35 class SkPDFShader;
36 class SkPDFStream;
37 
38 // Private classes.
39 struct ContentEntry;
40 struct GraphicStateEntry;
41 
42 class SkPDFDeviceFactory : public SkDeviceFactory {
43 public:
44     virtual SkDevice* newDevice(SkCanvas*, SkBitmap::Config, int width,
45                                 int height, bool isOpaque, bool isForLayer);
46 };
47 
48 /** \class SkPDFDevice
49 
50     The drawing context for the PDF backend.
51 */
52 class SkPDFDevice : public SkDevice {
53 public:
54     /** Create a PDF drawing context with the given width and height.
55      *  72 points/in means letter paper is 612x792.
56      *  @param pageSize Page size in points.
57      *  @param contentSize The content size of the page in points. This will be
58      *         combined with the initial transform to determine the drawing area
59      *         (as reported by the width and height methods). Anything outside
60      *         of the drawing area will be clipped.
61      *  @param initialTransform The initial transform to apply to the page.
62      *         This may be useful to, for example, move the origin in and
63      *         over a bit to account for a margin, scale the canvas,
64      *         or apply a rotation.  Note1: the SkPDFDevice also applies
65      *         a scale+translate transform to move the origin from the
66      *         bottom left (PDF default) to the top left.  Note2: drawDevice
67      *         (used by layer restore) draws the device after this initial
68      *         transform is applied, so the PDF device factory does an
69      *         inverse scale+translate to accommodate the one that SkPDFDevice
70      *         always does.
71      */
72     // TODO(vandebo) The sizes should be SkSize and not SkISize.
73     SK_API SkPDFDevice(const SkISize& pageSize, const SkISize& contentSize,
74                        const SkMatrix& initialTransform);
75     SK_API virtual ~SkPDFDevice();
76 
getDeviceCapabilities()77     virtual uint32_t getDeviceCapabilities() { return kVector_Capability; }
78 
79     virtual void clear(SkColor color);
80 
readPixels(const SkIRect & srcRect,SkBitmap * bitmap)81     virtual bool readPixels(const SkIRect& srcRect, SkBitmap* bitmap) {
82         return false;
83     }
84 
85     /** These are called inside the per-device-layer loop for each draw call.
86      When these are called, we have already applied any saveLayer operations,
87      and are handling any looping from the paint, and any effects from the
88      DrawFilter.
89      */
90     virtual void drawPaint(const SkDraw&, const SkPaint& paint);
91     virtual void drawPoints(const SkDraw&, SkCanvas::PointMode mode,
92                             size_t count, const SkPoint[],
93                             const SkPaint& paint);
94     virtual void drawRect(const SkDraw&, const SkRect& r, const SkPaint& paint);
95     virtual void drawPath(const SkDraw&, const SkPath& origpath,
96                           const SkPaint& paint, const SkMatrix* prePathMatrix,
97                           bool pathIsMutable);
98     virtual void drawBitmap(const SkDraw&, const SkBitmap& bitmap,
99                             const SkIRect* srcRectOrNull,
100                             const SkMatrix& matrix, const SkPaint& paint);
101     virtual void drawSprite(const SkDraw&, const SkBitmap& bitmap, int x, int y,
102                             const SkPaint& paint);
103     virtual void drawText(const SkDraw&, const void* text, size_t len,
104                           SkScalar x, SkScalar y, const SkPaint& paint);
105     virtual void drawPosText(const SkDraw&, const void* text, size_t len,
106                              const SkScalar pos[], SkScalar constY,
107                              int scalarsPerPos, const SkPaint& paint);
108     virtual void drawTextOnPath(const SkDraw&, const void* text, size_t len,
109                                 const SkPath& path, const SkMatrix* matrix,
110                                 const SkPaint& paint);
111     virtual void drawVertices(const SkDraw&, SkCanvas::VertexMode,
112                               int vertexCount, const SkPoint verts[],
113                               const SkPoint texs[], const SkColor colors[],
114                               SkXfermode* xmode, const uint16_t indices[],
115                               int indexCount, const SkPaint& paint);
116     virtual void drawDevice(const SkDraw&, SkDevice*, int x, int y,
117                             const SkPaint&);
118 
119     // PDF specific methods.
120 
121     /** Returns a reference to the resource dictionary for this device.
122      */
123     SK_API const SkRefPtr<SkPDFDict>& getResourceDict();
124 
125     /** Get the list of resources (PDF objects) used on this page.
126      *  @param resourceList A list to append the resources to.
127      */
128     SK_API void getResources(SkTDArray<SkPDFObject*>* resourceList) const;
129 
130     /** Get the fonts used on this device.
131      */
132     SK_API const SkTDArray<SkPDFFont*>& getFontResources() const;
133 
134     /** Returns the media box for this device.
135      */
136     SK_API SkRefPtr<SkPDFArray> getMediaBox() const;
137 
138     /** Returns a SkStream with the page contents.  The caller is responsible
139         for a reference to the returned value.
140      */
141     SK_API SkStream* content() const;
142 
initialTransform()143     SK_API const SkMatrix& initialTransform() const {
144         return fInitialTransform;
145     }
146 
147 protected:
148     // override
149     virtual SkDeviceFactory* onNewDeviceFactory();
150 
151 private:
152     friend class SkPDFDeviceFactory;
153     // TODO(vandebo) push most of SkPDFDevice's state into a core object in
154     // order to get the right access levels without using friend.
155     friend class ScopedContentEntry;
156 
157     SkISize fPageSize;
158     SkISize fContentSize;
159     SkMatrix fInitialTransform;
160     SkClipStack fExistingClipStack;
161     SkRegion fExistingClipRegion;
162     SkRefPtr<SkPDFDict> fResourceDict;
163 
164     SkTDArray<SkPDFGraphicState*> fGraphicStateResources;
165     SkTDArray<SkPDFObject*> fXObjectResources;
166     SkTDArray<SkPDFFont*> fFontResources;
167     SkTDArray<SkPDFShader*> fShaderResources;
168 
169     SkTScopedPtr<ContentEntry> fContentEntries;
170     ContentEntry* fLastContentEntry;
171 
172     // For use by the DeviceFactory.
173     SkPDFDevice(const SkISize& layerSize, const SkClipStack& existingClipStack,
174                 const SkRegion& existingClipRegion);
175 
176     void init();
177     void cleanUp();
178     void createFormXObjectFromDevice(SkRefPtr<SkPDFFormXObject>* xobject);
179 
180     // Clear the passed clip from all existing content entries.
181     void clearClipFromContent(const SkClipStack* clipStack,
182                               const SkRegion& clipRegion);
183     void drawFormXObjectWithClip(SkPDFFormXObject* form,
184                                  const SkClipStack* clipStack,
185                                  const SkRegion& clipRegion,
186                                  bool invertClip);
187 
188     // If the paint or clip is such that we shouldn't draw anything, this
189     // returns NULL and does not create a content entry.
190     // setUpContentEntry and finishContentEntry can be used directly, but
191     // the preferred method is to use the ScopedContentEntry helper class.
192     ContentEntry* setUpContentEntry(const SkClipStack* clipStack,
193                                     const SkRegion& clipRegion,
194                                     const SkMatrix& matrix,
195                                     const SkPaint& paint,
196                                     bool hasText,
197                                     SkRefPtr<SkPDFFormXObject>* dst);
198     void finishContentEntry(SkXfermode::Mode xfermode,
199                             SkPDFFormXObject* dst);
200     bool isContentEmpty();
201 
202     void populateGraphicStateEntryFromPaint(const SkMatrix& matrix,
203                                             const SkClipStack& clipStack,
204                                             const SkRegion& clipRegion,
205                                             const SkPaint& paint,
206                                             bool hasText,
207                                             GraphicStateEntry* entry);
208     int addGraphicStateResource(SkPDFGraphicState* gs);
209 
210     void updateFont(const SkPaint& paint, uint16_t glyphID,
211                     ContentEntry* contentEntry);
212     int getFontResourceIndex(SkTypeface* typeface, uint16_t glyphID);
213 
214     void internalDrawPaint(const SkPaint& paint, ContentEntry* contentEntry);
215     void internalDrawBitmap(const SkMatrix& matrix,
216                             const SkClipStack* clipStack,
217                             const SkRegion& clipRegion,
218                             const SkBitmap& bitmap,
219                             const SkIRect* srcRect,
220                             const SkPaint& paint);
221 
222     // Disable the default copy and assign implementation.
223     SkPDFDevice(const SkPDFDevice&);
224     void operator=(const SkPDFDevice&);
225 };
226 
227 #endif
228