blob: 094b794836284154b243f119065f5750ad9396b3 [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.comd03c2c72013-10-11 18:26:45 +000016class SkPdfAllocator;
edisonn@google.comb857a0c2013-06-25 20:45:40 +000017class SkPdfFont;
18class SkPdfDoc;
edisonn@google.comd03c2c72013-10-11 18:26:45 +000019class SkPdfNativeDoc;
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.comd03c2c72013-10-11 18:26:45 +000023#include "SkTypes.h"
edisonn@google.comb857a0c2013-06-25 20:45:40 +000024
edisonn@google.com3aac1f92013-07-02 22:42:53 +000025
edisonn@google.comd03c2c72013-10-11 18:26:45 +000026// TODO(edisonn): move SkTDStackNester class in its own private file
edisonn@google.comf68aed32013-08-22 15:37:21 +000027
28// Adobe limits it to 28, so 256 should be more than enough
29#define MAX_NESTING 256
30
edisonn@google.comd03c2c72013-10-11 18:26:45 +000031/** \class SkTDStackNester
32 *
33 * The difference between SkTDStackNester and SkTDStack is that:
34 * - SkTDStackNester uses new/delete to manage initializations
35 * - Supports nest/unnest which simulates a stack of stack. unnest will pop all the
36 * objects pushed since the last nest
37 */
38
39template <typename T> class SkTDStackNester : SkNoncopyable {
edisonn@google.com063d7072013-08-16 15:05:08 +000040public:
edisonn@google.comd03c2c72013-10-11 18:26:45 +000041 SkTDStackNester() : fCount(0), fTotalCount(0), fLocalCount(0) {
edisonn@google.com063d7072013-08-16 15:05:08 +000042 fInitialRec.fNext = NULL;
43 fRec = &fInitialRec;
44
45 // fCount = kSlotCount;
46 }
47
edisonn@google.comd03c2c72013-10-11 18:26:45 +000048 ~SkTDStackNester() {
edisonn@google.com063d7072013-08-16 15:05:08 +000049 Rec* rec = fRec;
50 while (rec != &fInitialRec) {
51 Rec* next = rec->fNext;
52 delete rec;
53 rec = next;
54 }
55 }
56
edisonn@google.comf68aed32013-08-22 15:37:21 +000057 int count() const { return fLocalCount; }
58 int depth() const { return fLocalCount; }
59 bool empty() const { return fLocalCount == 0; }
60
61 bool nests() {
62 return fNestingLevel;
63 }
64
65 void nest() {
66 // We are are past max nesting levels, we will still continue to work, but we might fail
67 // to properly ignore errors. Ideally it should only mean poor rendering in exceptional
68 // cases
69 if (fNestingLevel >= 0 && fNestingLevel < MAX_NESTING) {
70 fNestings[fNestingLevel] = fLocalCount;
71 fLocalCount = 0;
72 }
73 fNestingLevel++;
74 }
75
76 void unnest() {
77 SkASSERT(fNestingLevel > 0);
78 fNestingLevel--;
79 if (fNestingLevel >= 0 && fNestingLevel < MAX_NESTING) {
80 // TODO(edisonn): warn if fLocal > 0
81 while (fLocalCount > 0) {
82 pop();
83 }
84 fLocalCount = fNestings[fNestingLevel];
85 }
86 }
edisonn@google.com063d7072013-08-16 15:05:08 +000087
88 T* push() {
89 SkASSERT(fCount <= kSlotCount);
90 if (fCount == kSlotCount) {
91 Rec* rec = new Rec();
92 rec->fNext = fRec;
93 fRec = rec;
94 fCount = 0;
95 }
96 ++fTotalCount;
edisonn@google.comf68aed32013-08-22 15:37:21 +000097 ++fLocalCount;
edisonn@google.com063d7072013-08-16 15:05:08 +000098 return &fRec->fSlots[fCount++];
99 }
100
101 void push(const T& elem) { *this->push() = elem; }
102
103 const T& index(int idx) const {
104 SkASSERT(fRec && fCount > idx);
105 return fRec->fSlots[fCount - idx - 1];
106 }
107
108 T& index(int idx) {
109 SkASSERT(fRec && fCount > idx);
110 return fRec->fSlots[fCount - idx - 1];
111 }
112
113 const T& top() const {
114 SkASSERT(fRec && fCount > 0);
115 return fRec->fSlots[fCount - 1];
116 }
117
118 T& top() {
119 SkASSERT(fRec && fCount > 0);
120 return fRec->fSlots[fCount - 1];
121 }
122
123 void pop(T* elem) {
124 if (elem) {
125 *elem = fRec->fSlots[fCount - 1];
126 }
127 this->pop();
128 }
129
130 void pop() {
131 SkASSERT(fCount > 0 && fRec);
edisonn@google.comf68aed32013-08-22 15:37:21 +0000132 --fLocalCount;
edisonn@google.com063d7072013-08-16 15:05:08 +0000133 --fTotalCount;
134 if (--fCount == 0) {
135 if (fRec != &fInitialRec) {
136 Rec* rec = fRec->fNext;
137 delete fRec;
138 fCount = kSlotCount;
139 fRec = rec;
140 } else {
141 SkASSERT(fTotalCount == 0);
142 }
143 }
144 }
145
146private:
147 enum {
148 kSlotCount = 64
149 };
150
151 struct Rec;
152 friend struct Rec;
153
154 struct Rec {
155 Rec* fNext;
156 T fSlots[kSlotCount];
157 };
158 Rec fInitialRec;
159 Rec* fRec;
edisonn@google.comf68aed32013-08-22 15:37:21 +0000160 int fCount, fTotalCount, fLocalCount;
161 int fNestings[MAX_NESTING];
162 int fNestingLevel;
edisonn@google.com063d7072013-08-16 15:05:08 +0000163};
164
edisonn@google.comd03c2c72013-10-11 18:26:45 +0000165/** \class SkTDStackNester
166 * Operates on stroking or non-stroking properties.
167 */
edisonn@google.come2e01ff2013-08-02 20:24:48 +0000168class SkPdfColorOperator {
edisonn@google.coma0cefa12013-07-28 18:34:14 +0000169
170 /*
171 color space name or array The current color space in which color values are to be interpreted
172 (see Section 4.5, “Color Spaces”). There are two separate color space
173 parameters: one for stroking and one for all other painting opera-
174 tions. Initial value: DeviceGray.
175 */
176
177 // TODO(edisonn): implement the array part too
edisonn@google.come2e01ff2013-08-02 20:24:48 +0000178// TODO(edisonn): remove this public, let fields be private
edisonn@google.come2e01ff2013-08-02 20:24:48 +0000179public:
edisonn@google.com2ccc3af2013-07-23 17:43:18 +0000180 NotOwnedString fColorSpace;
edisonn@google.com3aa35552013-08-14 18:26:20 +0000181 SkPdfNativeObject* fPattern;
edisonn@google.coma0cefa12013-07-28 18:34:14 +0000182
183 /*
184 color (various) The current color to be used during painting operations (see Section
185 4.5, “Color Spaces”). The type and interpretation of this parameter
186 depend on the current color space; for most color spaces, a color
187 value consists of one to four numbers. There are two separate color
188 parameters: one for stroking and one for all other painting opera-
189 tions. Initial value: black.
190 */
191
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000192 SkColor fColor;
193 double fOpacity; // ca or CA
edisonn@google.come2e01ff2013-08-02 20:24:48 +0000194
edisonn@google.come2e01ff2013-08-02 20:24:48 +0000195public:
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000196 void setRGBColor(SkColor color) {
197 // TODO(edisonn): ASSERT DeviceRGB is the color space.
edisonn@google.come2e01ff2013-08-02 20:24:48 +0000198 fPattern = NULL;
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000199 fColor = color;
200 }
edisonn@google.comd03c2c72013-10-11 18:26:45 +0000201
202 // TODO(edisonn): implement the default values for all fields.
edisonn@google.come2e01ff2013-08-02 20:24:48 +0000203 SkPdfColorOperator() : fPattern(NULL), fColor(SK_ColorBLACK), fOpacity(1) {
204 NotOwnedString::init(&fColorSpace, "DeviceRGB");
205 }
206
207 void setColorSpace(NotOwnedString* colorSpace) {
208 fColorSpace = *colorSpace;
209 fPattern = NULL;
210 }
211
edisonn@google.com3aa35552013-08-14 18:26:20 +0000212 void setPatternColorSpace(SkPdfNativeObject* pattern) {
edisonn@google.come2e01ff2013-08-02 20:24:48 +0000213 fColorSpace.fBuffer = (const unsigned char*)"Pattern";
214 fColorSpace.fBytes = 7; // strlen("Pattern")
215 fPattern = pattern;
edisonn@google.com2ccc3af2013-07-23 17:43:18 +0000216 }
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000217
218 void applyGraphicsState(SkPaint* paint) {
edisonn@google.com96ba3aa2013-07-28 20:04:35 +0000219 paint->setColor(SkColorSetA(fColor, (U8CPU)(fOpacity * 255)));
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000220 }
221};
222
edisonn@google.comd03c2c72013-10-11 18:26:45 +0000223/** \class SkTDStackNester
224 * Operates on stroking or non-stroking properties.
225 */
edisonn@google.com3aac1f92013-07-02 22:42:53 +0000226struct SkPdfGraphicsState {
edisonn@google.coma0cefa12013-07-28 18:34:14 +0000227 // TODO(edisonn): deprecate and remove these!
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000228 double fCurPosX;
229 double fCurPosY;
230
231 double fCurFontSize;
232 bool fTextBlock;
233 SkPdfFont* fSkFont;
234 SkPath fPath;
235 bool fPathClosed;
236
edisonn@google.coma0cefa12013-07-28 18:34:14 +0000237 double fTextLeading;
238 double fWordSpace;
239 double fCharSpace;
240
241 SkPdfResourceDictionary* fResources;
242
243
edisonn@google.comd03c2c72013-10-11 18:26:45 +0000244 // TODO(edisonn): Can we move most of these in canvas/paint?
245 // Might need to strore some properties in 2 paints (stroking paint and non stroking paint)
edisonn@google.coma0cefa12013-07-28 18:34:14 +0000246
247// TABLE 4.2 Device-independent graphics state parameters
248/*
249 * CTM array The current transformation matrix, which maps positions from user
250 coordinates to device coordinates (see Section 4.2, “Coordinate Sys-
251 tems”). This matrix is modified by each application of the coordi-
252 nate transformation operator, cm. Initial value: a matrix that
253 transforms default user coordinates to device coordinates.
254 */
255 SkMatrix fCTM;
256
edisonn@google.com0f901902013-08-07 11:56:16 +0000257 SkMatrix fContentStreamMatrix;
258
edisonn@google.coma0cefa12013-07-28 18:34:14 +0000259/*
260clipping path (internal) The current clipping path, which defines the boundary against
261 which all output is to be cropped (see Section 4.4.3, “Clipping Path
262 Operators”). Initial value: the boundary of the entire imageable
263 portion of the output page.
264 */
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000265 // Clip that is applied after the drawing is done!!!
266 bool fHasClipPathToApply;
267 SkPath fClipPath;
268
edisonn@google.com3aac1f92013-07-02 22:42:53 +0000269 SkPdfColorOperator fStroking;
270 SkPdfColorOperator fNonStroking;
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000271
edisonn@google.coma0cefa12013-07-28 18:34:14 +0000272/*
273text state (various) A set of nine graphics state parameters that pertain only to the
274 painting of text. These include parameters that select the font, scale
275 the glyphs to an appropriate size, and accomplish other effects. The
276 text state parameters are described in Section 5.2, “Text State
277 Parameters and Operators.”
278 */
279
280 // TODO(edisonn): add SkPdfTextState class. remove these two existing fields
281 SkMatrix fMatrixTm;
282 SkMatrix fMatrixTlm;
283
284
285/*
286line width number The thickness, in user space units, of paths to be stroked (see “Line
287 Width” on page 152). Initial value: 1.0.
288 */
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000289 double fLineWidth;
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000290
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000291
edisonn@google.coma0cefa12013-07-28 18:34:14 +0000292/*
293line cap integer A code specifying the shape of the endpoints for any open path that
294 is stroked (see “Line Cap Style” on page 153). Initial value: 0, for
295 square butt caps.
296 */
297 // TODO (edisonn): implement defaults - page 153
298 int fLineCap;
299
300/*
301line join integer A code specifying the shape of joints between connected segments
302 of a stroked path (see “Line Join Style” on page 153). Initial value: 0,
303 for mitered joins.
304 */
305 // TODO (edisonn): implement defaults - page 153
306 int fLineJoin;
307
308/*
309miter limit number The maximum length of mitered line joins for stroked paths (see
310 “Miter Limit” on page 153). This parameter limits the length of
311 “spikes” produced when line segments join at sharp angles. Initial
312 value: 10.0, for a miter cutoff below approximately 11.5 degrees.
313 */
314 // TODO (edisonn): implement defaults - page 153
315 double fMiterLimit;
316
317/*
318dash pattern array and A description of the dash pattern to be used when paths are
319 number stroked (see “Line Dash Pattern” on page 155). Initial value: a solid
320 line.
321 */
322 SkScalar fDashArray[256]; // TODO(edisonn): allocate array?
323 int fDashArrayLength;
324 SkScalar fDashPhase;
325
326
327/*
328rendering intent name The rendering intent to be used when converting CIE-based colors
329 to device colors (see “Rendering Intents” on page 197). Default
330 value: RelativeColorimetric.
331 */
332 // TODO(edisonn): seems paper only. Verify.
333
334/*
335stroke adjustment boolean (PDF 1.2) A flag specifying whether to compensate for possible ras-
336 terization effects when stroking a path with a line width that is
337 small relative to the pixel resolution of the output device (see Sec-
338 tion 6.5.4, “Automatic Stroke Adjustment”). Note that this is con-
339 sidered a device-independent parameter, even though the details of
340 its effects are device-dependent. Initial value: false.
341 */
342 // TODO(edisonn): stroke adjustment low priority.
343
344
345/*
346blend mode name or array (PDF 1.4) The current blend mode to be used in the transparent
347 imaging model (see Sections 7.2.4, “Blend Mode,” and 7.5.2, “Spec-
348 ifying Blending Color Space and Blend Mode”). This parameter is
349 implicitly reset to its initial value at the beginning of execution of a
350 transparency group XObject (see Section 7.5.5, “Transparency
351 Group XObjects”). Initial value: Normal.
352 */
edisonn@google.come878e722013-07-29 19:10:58 +0000353 SkXfermode::Mode fBlendModes[256];
354 int fBlendModesLength;
edisonn@google.coma0cefa12013-07-28 18:34:14 +0000355
356/*
357soft mask dictionary (PDF 1.4) A soft-mask dictionary (see “Soft-Mask Dictionaries” on
358 or name page 445) specifying the mask shape or mask opacity values to be
359 used in the transparent imaging model (see “Source Shape and
360 Opacity” on page 421 and “Mask Shape and Opacity” on page 443),
361 or the name None if no such mask is specified. This parameter is
362 implicitly reset to its initial value at the beginning of execution of a
363 transparency group XObject (see Section 7.5.5, “Transparency
364 Group XObjects”). Initial value: None.
365 */
edisonn@google.com4ef4bed2013-07-29 22:14:45 +0000366 SkPdfSoftMaskDictionary* fSoftMaskDictionary;
edisonn@google.comb0145ce2013-08-05 16:23:23 +0000367 // TODO(edisonn): make sMask private, add setter and getter, ref/unref/..., at the moment we most likely leask
368 SkBitmap* fSMask;
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000369
edisonn@google.coma0cefa12013-07-28 18:34:14 +0000370
371/*
372alpha constant number (PDF 1.4) The constant shape or constant opacity value to be used
373 in the transparent imaging model (see “Source Shape and Opacity”
374 on page 421 and “Constant Shape and Opacity” on page 444).
375 There are two separate alpha constant parameters: one for stroking
376 and one for all other painting operations. This parameter is implic-
377 itly reset to its initial value at the beginning of execution of a trans-
378 parency group XObject (see Section 7.5.5, “Transparency Group
379 XObjects”). Initial value: 1.0.
380 */
381 double fAphaConstant;
382
383/*
384alpha source boolean (PDF 1.4) A flag specifying whether the current soft mask and alpha
385 constant parameters are to be interpreted as shape values (true) or
386 opacity values (false). This flag also governs the interpretation of
387 the SMask entry, if any, in an image dictionary (see Section 4.8.4,
388 “Image Dictionaries”). Initial value: false.
389 */
390 bool fAlphaSource;
391
392
393// TODO(edisonn): Device-dependent seem to be required only on the actual physical printer?
394// TABLE 4.3 Device-dependent graphics state parameters
395/*
396overprint boolean (PDF 1.2) A flag specifying (on output devices that support the
397 overprint control feature) whether painting in one set of colorants
398 should cause the corresponding areas of other colorants to be
399 erased (false) or left unchanged (true); see Section 4.5.6, “Over-
400 print Control.” In PDF 1.3, there are two separate overprint param-
401 eters: one for stroking and one for all other painting operations.
402 Initial value: false.
403 */
404
405
406/*
407overprint mode number (PDF 1.3) A code specifying whether a color component value of 0
408 in a DeviceCMYK color space should erase that component (0) or
409 leave it unchanged (1) when overprinting (see Section 4.5.6, “Over-
410 print Control”). Initial value: 0.
411 */
412
413
414/*
415black generation function (PDF 1.2) A function that calculates the level of the black color
416 or name component to use when converting RGB colors to CMYK (see Sec-
417 tion 6.2.3, “Conversion from DeviceRGB to DeviceCMYK”). Initial
418 value: installation-dependent.
419 */
420
421
422/*
423undercolor removal function (PDF 1.2) A function that calculates the reduction in the levels of
424 or name the cyan, magenta, and yellow color components to compensate for
425 the amount of black added by black generation (see Section 6.2.3,
426 “Conversion from DeviceRGB to DeviceCMYK”). Initial value: in-
427 stallation-dependent.
428 */
429
430
431/*
432transfer function, (PDF 1.2) A function that adjusts device gray or color component
433 array, or name levels to compensate for nonlinear response in a particular out-
434 put device (see Section 6.3, “Transfer Functions”). Initial value:
435 installation-dependent.
436 */
437
438
439/*
440halftone dictionary, (PDF 1.2) A halftone screen for gray and color rendering, specified
441 stream, or name as a halftone dictionary or stream (see Section 6.4, “Halftones”).
442 Initial value: installation-dependent.
443 */
444
445
446/*
447flatness number The precision with which curves are to be rendered on the output
448 device (see Section 6.5.1, “Flatness Tolerance”). The value of this
449 parameter gives the maximum error tolerance, measured in output
450 device pixels; smaller numbers give smoother curves at the expense
451 of more computation and memory use. Initial value: 1.0.
452 */
453
454
455/*
456smoothness number (PDF 1.3) The precision with which color gradients are to be ren-
457 dered on the output device (see Section 6.5.2, “Smoothness Toler-
458 ance”). The value of this parameter gives the maximum error
459 tolerance, expressed as a fraction of the range of each color compo-
460 nent; smaller numbers give smoother color transitions at the
461 expense of more computation and memory use. Initial value:
462 installation-dependent.
463 */
464
edisonn@google.come50d9a12013-10-10 20:58:22 +0000465 // TODO(edisonn): some defaults are contextual, they could on colorspace, pdf version, ...
edisonn@google.com3aac1f92013-07-02 22:42:53 +0000466 SkPdfGraphicsState() {
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000467 fCurPosX = 0.0;
468 fCurPosY = 0.0;
469 fCurFontSize = 0.0;
470 fTextBlock = false;
edisonn@google.coma0cefa12013-07-28 18:34:14 +0000471 fCTM = SkMatrix::I();
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000472 fMatrixTm = SkMatrix::I();
473 fMatrixTlm = SkMatrix::I();
474 fPathClosed = true;
475 fLineWidth = 0;
476 fTextLeading = 0;
477 fWordSpace = 0;
478 fCharSpace = 0;
479 fHasClipPathToApply = false;
480 fResources = NULL;
481 fSkFont = NULL;
edisonn@google.coma0cefa12013-07-28 18:34:14 +0000482 fLineCap = 0;
483 fLineJoin = 0;
484 fMiterLimit = 10.0;
485 fAphaConstant = 1.0;
486 fAlphaSource = false;
487 fDashArrayLength = 0;
488 fDashPhase = 0;
edisonn@google.come878e722013-07-29 19:10:58 +0000489 fBlendModesLength = 1;
490 fBlendModes[0] = SkXfermode::kSrc_Mode; // PDF: Normal Blend mode
edisonn@google.com91ce6982013-08-05 20:45:40 +0000491 fSMask = NULL;
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000492 }
493
edisonn@google.come50d9a12013-10-10 20:58:22 +0000494 // TODO(edisonn): make two functions instead, stroking and non stoking, avoid branching
edisonn@google.coma0cefa12013-07-28 18:34:14 +0000495 void applyGraphicsState(SkPaint* paint, bool stroking);
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000496};
497
edisonn@google.comd03c2c72013-10-11 18:26:45 +0000498/** \class SkPdfContext
499 * The context of the drawing. The document we draw from, the current stack of objects, ...
500 */
edisonn@google.com33f11b62013-08-14 21:35:27 +0000501class SkPdfContext {
502public:
edisonn@google.comd03c2c72013-10-11 18:26:45 +0000503 SkTDStackNester<SkPdfNativeObject*> fObjectStack;
504 SkTDStackNester<SkPdfGraphicsState> fStateStack;
edisonn@google.com3aac1f92013-07-02 22:42:53 +0000505 SkPdfGraphicsState fGraphicsState;
edisonn@google.com33f11b62013-08-14 21:35:27 +0000506 SkPdfNativeDoc* fPdfDoc;
edisonn@google.com2ccc3af2013-07-23 17:43:18 +0000507 SkPdfAllocator* fTmpPageAllocator;
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000508 SkMatrix fOriginalMatrix;
509
edisonn@google.com3aa35552013-08-14 18:26:20 +0000510 SkPdfContext(SkPdfNativeDoc* doc);
511 ~SkPdfContext();
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000512};
513
edisonn@google.comcf2cfa12013-08-21 16:31:37 +0000514#endif // SkPdfGraphicsState_DEFINED