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