blob: 0928f443e01c60109676347c8f6e2f2c7bfe5101 [file] [log] [blame]
edisonn@google.comcf2cfa12013-08-21 16:31:37 +00001/*
2 * Copyright 2013 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 SkPdfGraphicsState_DEFINED
9#define SkPdfGraphicsState_DEFINED
edisonn@google.comb857a0c2013-06-25 20:45:40 +000010
edisonn@google.com131d4ee2013-06-26 17:48:12 +000011#include "SkCanvas.h"
12#include "SkPaint.h"
edisonn@google.com3aac1f92013-07-02 22:42:53 +000013#include "SkPdfConfig.h"
edisonn@google.com3aa35552013-08-14 18:26:20 +000014#include "SkPdfUtils.h"
edisonn@google.com131d4ee2013-06-26 17:48:12 +000015
edisonn@google.com063d7072013-08-16 15:05:08 +000016//#include "SkTDStack.h"
edisonn@google.comb857a0c2013-06-25 20:45:40 +000017
edisonn@google.comb857a0c2013-06-25 20:45:40 +000018class SkPdfFont;
19class SkPdfDoc;
edisonn@google.com3aa35552013-08-14 18:26:20 +000020class SkPdfNativeObject;
edisonn@google.com131d4ee2013-06-26 17:48:12 +000021class SkPdfResourceDictionary;
edisonn@google.com4ef4bed2013-07-29 22:14:45 +000022class SkPdfSoftMaskDictionary;
edisonn@google.comb857a0c2013-06-25 20:45:40 +000023
edisonn@google.com3aa35552013-08-14 18:26:20 +000024class SkPdfNativeDoc;
edisonn@google.com2ccc3af2013-07-23 17:43:18 +000025class SkPdfAllocator;
edisonn@google.com3aac1f92013-07-02 22:42:53 +000026
edisonn@google.com063d7072013-08-16 15:05:08 +000027// TODO(edisonn): move this class in iclude/core?
28// Ref objects can't be dealt unless we use a specific class initialization
29// The difference between SkTDStackNew and SkTDStack is that SkTDStackNew uses new/delete
30// to be a manage c++ stuff (like initializations)
31#include "SkTypes.h"
32template <typename T> class SkTDStackNew : SkNoncopyable {
33public:
34 SkTDStackNew() : fCount(0), fTotalCount(0) {
35 fInitialRec.fNext = NULL;
36 fRec = &fInitialRec;
37
38 // fCount = kSlotCount;
39 }
40
41 ~SkTDStackNew() {
42 Rec* rec = fRec;
43 while (rec != &fInitialRec) {
44 Rec* next = rec->fNext;
45 delete rec;
46 rec = next;
47 }
48 }
49
50 int count() const { return fTotalCount; }
51 int depth() const { return fTotalCount; }
52 bool empty() const { return fTotalCount == 0; }
53
54 T* push() {
55 SkASSERT(fCount <= kSlotCount);
56 if (fCount == kSlotCount) {
57 Rec* rec = new Rec();
58 rec->fNext = fRec;
59 fRec = rec;
60 fCount = 0;
61 }
62 ++fTotalCount;
63 return &fRec->fSlots[fCount++];
64 }
65
66 void push(const T& elem) { *this->push() = elem; }
67
68 const T& index(int idx) const {
69 SkASSERT(fRec && fCount > idx);
70 return fRec->fSlots[fCount - idx - 1];
71 }
72
73 T& index(int idx) {
74 SkASSERT(fRec && fCount > idx);
75 return fRec->fSlots[fCount - idx - 1];
76 }
77
78 const T& top() const {
79 SkASSERT(fRec && fCount > 0);
80 return fRec->fSlots[fCount - 1];
81 }
82
83 T& top() {
84 SkASSERT(fRec && fCount > 0);
85 return fRec->fSlots[fCount - 1];
86 }
87
88 void pop(T* elem) {
89 if (elem) {
90 *elem = fRec->fSlots[fCount - 1];
91 }
92 this->pop();
93 }
94
95 void pop() {
96 SkASSERT(fCount > 0 && fRec);
97 --fTotalCount;
98 if (--fCount == 0) {
99 if (fRec != &fInitialRec) {
100 Rec* rec = fRec->fNext;
101 delete fRec;
102 fCount = kSlotCount;
103 fRec = rec;
104 } else {
105 SkASSERT(fTotalCount == 0);
106 }
107 }
108 }
109
110private:
111 enum {
112 kSlotCount = 64
113 };
114
115 struct Rec;
116 friend struct Rec;
117
118 struct Rec {
119 Rec* fNext;
120 T fSlots[kSlotCount];
121 };
122 Rec fInitialRec;
123 Rec* fRec;
124 int fCount, fTotalCount;
125};
126
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000127// TODO(edisonn): better class design.
edisonn@google.come2e01ff2013-08-02 20:24:48 +0000128class SkPdfColorOperator {
edisonn@google.coma0cefa12013-07-28 18:34:14 +0000129
130 /*
131 color space name or array The current color space in which color values are to be interpreted
132 (see Section 4.5, “Color Spaces”). There are two separate color space
133 parameters: one for stroking and one for all other painting opera-
134 tions. Initial value: DeviceGray.
135 */
136
137 // TODO(edisonn): implement the array part too
edisonn@google.com571c70b2013-07-10 17:09:50 +0000138 // does not own the char*
edisonn@google.come2e01ff2013-08-02 20:24:48 +0000139// TODO(edisonn): remove this public, let fields be private
140// TODO(edisonn): make color space an enum!
141public:
edisonn@google.com2ccc3af2013-07-23 17:43:18 +0000142 NotOwnedString fColorSpace;
edisonn@google.com3aa35552013-08-14 18:26:20 +0000143 SkPdfNativeObject* fPattern;
edisonn@google.coma0cefa12013-07-28 18:34:14 +0000144
145 /*
146 color (various) The current color to be used during painting operations (see Section
147 4.5, “Color Spaces”). The type and interpretation of this parameter
148 depend on the current color space; for most color spaces, a color
149 value consists of one to four numbers. There are two separate color
150 parameters: one for stroking and one for all other painting opera-
151 tions. Initial value: black.
152 */
153
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000154 SkColor fColor;
155 double fOpacity; // ca or CA
edisonn@google.come2e01ff2013-08-02 20:24:48 +0000156
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000157 // TODO(edisonn): add here other color space options.
158
edisonn@google.come2e01ff2013-08-02 20:24:48 +0000159public:
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000160 void setRGBColor(SkColor color) {
161 // TODO(edisonn): ASSERT DeviceRGB is the color space.
edisonn@google.come2e01ff2013-08-02 20:24:48 +0000162 fPattern = NULL;
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000163 fColor = color;
164 }
165 // TODO(edisonn): double check the default values for all fields.
edisonn@google.come2e01ff2013-08-02 20:24:48 +0000166 SkPdfColorOperator() : fPattern(NULL), fColor(SK_ColorBLACK), fOpacity(1) {
167 NotOwnedString::init(&fColorSpace, "DeviceRGB");
168 }
169
170 void setColorSpace(NotOwnedString* colorSpace) {
171 fColorSpace = *colorSpace;
172 fPattern = NULL;
173 }
174
edisonn@google.com3aa35552013-08-14 18:26:20 +0000175 void setPatternColorSpace(SkPdfNativeObject* pattern) {
edisonn@google.come2e01ff2013-08-02 20:24:48 +0000176 fColorSpace.fBuffer = (const unsigned char*)"Pattern";
177 fColorSpace.fBytes = 7; // strlen("Pattern")
178 fPattern = pattern;
edisonn@google.com2ccc3af2013-07-23 17:43:18 +0000179 }
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000180
181 void applyGraphicsState(SkPaint* paint) {
edisonn@google.com96ba3aa2013-07-28 20:04:35 +0000182 paint->setColor(SkColorSetA(fColor, (U8CPU)(fOpacity * 255)));
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000183 }
184};
185
186// TODO(edisonn): better class design.
edisonn@google.com3aac1f92013-07-02 22:42:53 +0000187struct SkPdfGraphicsState {
edisonn@google.coma0cefa12013-07-28 18:34:14 +0000188 // TODO(edisonn): deprecate and remove these!
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000189 double fCurPosX;
190 double fCurPosY;
191
192 double fCurFontSize;
193 bool fTextBlock;
194 SkPdfFont* fSkFont;
195 SkPath fPath;
196 bool fPathClosed;
197
edisonn@google.coma0cefa12013-07-28 18:34:14 +0000198 double fTextLeading;
199 double fWordSpace;
200 double fCharSpace;
201
202 SkPdfResourceDictionary* fResources;
203
204
205 // TODO(edisonn): move most of these in canvas/paint?
206 // we could have some in canvas (matrixes?),
207 // some in 2 paints (stroking paint and non stroking paint)
208
209// TABLE 4.2 Device-independent graphics state parameters
210/*
211 * CTM array The current transformation matrix, which maps positions from user
212 coordinates to device coordinates (see Section 4.2, “Coordinate Sys-
213 tems”). This matrix is modified by each application of the coordi-
214 nate transformation operator, cm. Initial value: a matrix that
215 transforms default user coordinates to device coordinates.
216 */
217 SkMatrix fCTM;
218
edisonn@google.com0f901902013-08-07 11:56:16 +0000219 SkMatrix fContentStreamMatrix;
220
edisonn@google.coma0cefa12013-07-28 18:34:14 +0000221/*
222clipping path (internal) The current clipping path, which defines the boundary against
223 which all output is to be cropped (see Section 4.4.3, “Clipping Path
224 Operators”). Initial value: the boundary of the entire imageable
225 portion of the output page.
226 */
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000227 // Clip that is applied after the drawing is done!!!
228 bool fHasClipPathToApply;
229 SkPath fClipPath;
230
edisonn@google.com3aac1f92013-07-02 22:42:53 +0000231 SkPdfColorOperator fStroking;
232 SkPdfColorOperator fNonStroking;
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000233
edisonn@google.coma0cefa12013-07-28 18:34:14 +0000234/*
235text state (various) A set of nine graphics state parameters that pertain only to the
236 painting of text. These include parameters that select the font, scale
237 the glyphs to an appropriate size, and accomplish other effects. The
238 text state parameters are described in Section 5.2, “Text State
239 Parameters and Operators.”
240 */
241
242 // TODO(edisonn): add SkPdfTextState class. remove these two existing fields
243 SkMatrix fMatrixTm;
244 SkMatrix fMatrixTlm;
245
246
247/*
248line width number The thickness, in user space units, of paths to be stroked (see “Line
249 Width” on page 152). Initial value: 1.0.
250 */
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000251 double fLineWidth;
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000252
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000253
edisonn@google.coma0cefa12013-07-28 18:34:14 +0000254/*
255line cap integer A code specifying the shape of the endpoints for any open path that
256 is stroked (see “Line Cap Style” on page 153). Initial value: 0, for
257 square butt caps.
258 */
259 // TODO (edisonn): implement defaults - page 153
260 int fLineCap;
261
262/*
263line join integer A code specifying the shape of joints between connected segments
264 of a stroked path (see “Line Join Style” on page 153). Initial value: 0,
265 for mitered joins.
266 */
267 // TODO (edisonn): implement defaults - page 153
268 int fLineJoin;
269
270/*
271miter limit number The maximum length of mitered line joins for stroked paths (see
272 “Miter Limit” on page 153). This parameter limits the length of
273 “spikes” produced when line segments join at sharp angles. Initial
274 value: 10.0, for a miter cutoff below approximately 11.5 degrees.
275 */
276 // TODO (edisonn): implement defaults - page 153
277 double fMiterLimit;
278
279/*
280dash pattern array and A description of the dash pattern to be used when paths are
281 number stroked (see “Line Dash Pattern” on page 155). Initial value: a solid
282 line.
283 */
284 SkScalar fDashArray[256]; // TODO(edisonn): allocate array?
285 int fDashArrayLength;
286 SkScalar fDashPhase;
287
288
289/*
290rendering intent name The rendering intent to be used when converting CIE-based colors
291 to device colors (see “Rendering Intents” on page 197). Default
292 value: RelativeColorimetric.
293 */
294 // TODO(edisonn): seems paper only. Verify.
295
296/*
297stroke adjustment boolean (PDF 1.2) A flag specifying whether to compensate for possible ras-
298 terization effects when stroking a path with a line width that is
299 small relative to the pixel resolution of the output device (see Sec-
300 tion 6.5.4, “Automatic Stroke Adjustment”). Note that this is con-
301 sidered a device-independent parameter, even though the details of
302 its effects are device-dependent. Initial value: false.
303 */
304 // TODO(edisonn): stroke adjustment low priority.
305
306
307/*
308blend mode name or array (PDF 1.4) The current blend mode to be used in the transparent
309 imaging model (see Sections 7.2.4, “Blend Mode,” and 7.5.2, “Spec-
310 ifying Blending Color Space and Blend Mode”). This parameter is
311 implicitly reset to its initial value at the beginning of execution of a
312 transparency group XObject (see Section 7.5.5, “Transparency
313 Group XObjects”). Initial value: Normal.
314 */
edisonn@google.come878e722013-07-29 19:10:58 +0000315 SkXfermode::Mode fBlendModes[256];
316 int fBlendModesLength;
edisonn@google.coma0cefa12013-07-28 18:34:14 +0000317
318/*
319soft mask dictionary (PDF 1.4) A soft-mask dictionary (see “Soft-Mask Dictionaries” on
320 or name page 445) specifying the mask shape or mask opacity values to be
321 used in the transparent imaging model (see “Source Shape and
322 Opacity” on page 421 and “Mask Shape and Opacity” on page 443),
323 or the name None if no such mask is specified. This parameter is
324 implicitly reset to its initial value at the beginning of execution of a
325 transparency group XObject (see Section 7.5.5, “Transparency
326 Group XObjects”). Initial value: None.
327 */
edisonn@google.com4ef4bed2013-07-29 22:14:45 +0000328 SkPdfSoftMaskDictionary* fSoftMaskDictionary;
edisonn@google.comb0145ce2013-08-05 16:23:23 +0000329 // TODO(edisonn): make sMask private, add setter and getter, ref/unref/..., at the moment we most likely leask
330 SkBitmap* fSMask;
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000331
edisonn@google.coma0cefa12013-07-28 18:34:14 +0000332
333/*
334alpha constant number (PDF 1.4) The constant shape or constant opacity value to be used
335 in the transparent imaging model (see “Source Shape and Opacity”
336 on page 421 and “Constant Shape and Opacity” on page 444).
337 There are two separate alpha constant parameters: one for stroking
338 and one for all other painting operations. This parameter is implic-
339 itly reset to its initial value at the beginning of execution of a trans-
340 parency group XObject (see Section 7.5.5, “Transparency Group
341 XObjects”). Initial value: 1.0.
342 */
343 double fAphaConstant;
344
345/*
346alpha source boolean (PDF 1.4) A flag specifying whether the current soft mask and alpha
347 constant parameters are to be interpreted as shape values (true) or
348 opacity values (false). This flag also governs the interpretation of
349 the SMask entry, if any, in an image dictionary (see Section 4.8.4,
350 “Image Dictionaries”). Initial value: false.
351 */
352 bool fAlphaSource;
353
354
355// TODO(edisonn): Device-dependent seem to be required only on the actual physical printer?
356// TABLE 4.3 Device-dependent graphics state parameters
357/*
358overprint boolean (PDF 1.2) A flag specifying (on output devices that support the
359 overprint control feature) whether painting in one set of colorants
360 should cause the corresponding areas of other colorants to be
361 erased (false) or left unchanged (true); see Section 4.5.6, “Over-
362 print Control.” In PDF 1.3, there are two separate overprint param-
363 eters: one for stroking and one for all other painting operations.
364 Initial value: false.
365 */
366
367
368/*
369overprint mode number (PDF 1.3) A code specifying whether a color component value of 0
370 in a DeviceCMYK color space should erase that component (0) or
371 leave it unchanged (1) when overprinting (see Section 4.5.6, “Over-
372 print Control”). Initial value: 0.
373 */
374
375
376/*
377black generation function (PDF 1.2) A function that calculates the level of the black color
378 or name component to use when converting RGB colors to CMYK (see Sec-
379 tion 6.2.3, “Conversion from DeviceRGB to DeviceCMYK”). Initial
380 value: installation-dependent.
381 */
382
383
384/*
385undercolor removal function (PDF 1.2) A function that calculates the reduction in the levels of
386 or name the cyan, magenta, and yellow color components to compensate for
387 the amount of black added by black generation (see Section 6.2.3,
388 “Conversion from DeviceRGB to DeviceCMYK”). Initial value: in-
389 stallation-dependent.
390 */
391
392
393/*
394transfer function, (PDF 1.2) A function that adjusts device gray or color component
395 array, or name levels to compensate for nonlinear response in a particular out-
396 put device (see Section 6.3, “Transfer Functions”). Initial value:
397 installation-dependent.
398 */
399
400
401/*
402halftone dictionary, (PDF 1.2) A halftone screen for gray and color rendering, specified
403 stream, or name as a halftone dictionary or stream (see Section 6.4, “Halftones”).
404 Initial value: installation-dependent.
405 */
406
407
408/*
409flatness number The precision with which curves are to be rendered on the output
410 device (see Section 6.5.1, “Flatness Tolerance”). The value of this
411 parameter gives the maximum error tolerance, measured in output
412 device pixels; smaller numbers give smoother curves at the expense
413 of more computation and memory use. Initial value: 1.0.
414 */
415
416
417/*
418smoothness number (PDF 1.3) The precision with which color gradients are to be ren-
419 dered on the output device (see Section 6.5.2, “Smoothness Toler-
420 ance”). The value of this parameter gives the maximum error
421 tolerance, expressed as a fraction of the range of each color compo-
422 nent; smaller numbers give smoother color transitions at the
423 expense of more computation and memory use. Initial value:
424 installation-dependent.
425 */
426
427
428
429
430
431
432
edisonn@google.com3aac1f92013-07-02 22:42:53 +0000433 SkPdfGraphicsState() {
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000434 fCurPosX = 0.0;
435 fCurPosY = 0.0;
436 fCurFontSize = 0.0;
437 fTextBlock = false;
edisonn@google.coma0cefa12013-07-28 18:34:14 +0000438 fCTM = SkMatrix::I();
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000439 fMatrixTm = SkMatrix::I();
440 fMatrixTlm = SkMatrix::I();
441 fPathClosed = true;
442 fLineWidth = 0;
443 fTextLeading = 0;
444 fWordSpace = 0;
445 fCharSpace = 0;
446 fHasClipPathToApply = false;
447 fResources = NULL;
448 fSkFont = NULL;
edisonn@google.coma0cefa12013-07-28 18:34:14 +0000449 fLineCap = 0;
450 fLineJoin = 0;
451 fMiterLimit = 10.0;
452 fAphaConstant = 1.0;
453 fAlphaSource = false;
454 fDashArrayLength = 0;
455 fDashPhase = 0;
edisonn@google.come878e722013-07-29 19:10:58 +0000456 fBlendModesLength = 1;
457 fBlendModes[0] = SkXfermode::kSrc_Mode; // PDF: Normal Blend mode
edisonn@google.com91ce6982013-08-05 20:45:40 +0000458 fSMask = NULL;
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000459 }
460
edisonn@google.coma0cefa12013-07-28 18:34:14 +0000461 // TODO(edisonn): make two functons instead, stroking and non stoking, avoid branching
462 void applyGraphicsState(SkPaint* paint, bool stroking);
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000463};
464
465// TODO(edisonn): better class design.
edisonn@google.com3aac1f92013-07-02 22:42:53 +0000466// TODO(edisonn): rename to SkPdfContext
edisonn@google.com33f11b62013-08-14 21:35:27 +0000467class SkPdfContext {
468public:
edisonn@google.com063d7072013-08-16 15:05:08 +0000469 SkTDStackNew<SkPdfNativeObject*> fObjectStack;
470 SkTDStackNew<SkPdfGraphicsState> fStateStack;
edisonn@google.com3aac1f92013-07-02 22:42:53 +0000471 SkPdfGraphicsState fGraphicsState;
edisonn@google.com33f11b62013-08-14 21:35:27 +0000472 SkPdfNativeDoc* fPdfDoc;
edisonn@google.com2ccc3af2013-07-23 17:43:18 +0000473 // TODO(edisonn): the allocator, could be freed after the page is done drawing.
474 SkPdfAllocator* fTmpPageAllocator;
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000475 SkMatrix fOriginalMatrix;
476
edisonn@google.com3aa35552013-08-14 18:26:20 +0000477 SkPdfContext(SkPdfNativeDoc* doc);
478 ~SkPdfContext();
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000479};
480
edisonn@google.comcf2cfa12013-08-21 16:31:37 +0000481#endif // SkPdfGraphicsState_DEFINED