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