1 | //======================================================================== |
2 | // |
3 | // GfxState.h |
4 | // |
5 | // Copyright 1996-2003 Glyph & Cog, LLC |
6 | // |
7 | //======================================================================== |
8 | |
9 | //======================================================================== |
10 | // |
11 | // Modified under the Poppler project - http://poppler.freedesktop.org |
12 | // |
13 | // All changes made under the Poppler project to this file are licensed |
14 | // under GPL version 2 or later |
15 | // |
16 | // Copyright (C) 2005 Kristian Høgsberg <krh@redhat.com> |
17 | // Copyright (C) 2006, 2007 Jeff Muizelaar <jeff@infidigm.net> |
18 | // Copyright (C) 2006 Carlos Garcia Campos <carlosgc@gnome.org> |
19 | // Copyright (C) 2009 Koji Otani <sho@bbr.jp> |
20 | // Copyright (C) 2009-2011, 2013, 2016-2022 Albert Astals Cid <aacid@kde.org> |
21 | // Copyright (C) 2010 Christian Feuersänger <cfeuersaenger@googlemail.com> |
22 | // Copyright (C) 2011 Andrea Canciani <ranma42@gmail.com> |
23 | // Copyright (C) 2011-2014, 2016, 2020 Thomas Freitag <Thomas.Freitag@alfa.de> |
24 | // Copyright (C) 2013 Lu Wang <coolwanglu@gmail.com> |
25 | // Copyright (C) 2015, 2017, 2020, 2022 Adrian Johnson <ajohnson@redneon.com> |
26 | // Copyright (C) 2017, 2019, 2022 Oliver Sander <oliver.sander@tu-dresden.de> |
27 | // Copyright (C) 2018 Adam Reichold <adam.reichold@t-online.de> |
28 | // Copyright (C) 2020, 2021 Philipp Knechtges <philipp-dev@knechtges.com> |
29 | // |
30 | // To see a description of the changes please see the Changelog file that |
31 | // came with your tarball or type make ChangeLog if you are building from git |
32 | // |
33 | //======================================================================== |
34 | |
35 | #ifndef GFXSTATE_H |
36 | #define GFXSTATE_H |
37 | |
38 | #include "poppler-config.h" |
39 | #include "poppler_private_export.h" |
40 | |
41 | #include "Object.h" |
42 | #include "Function.h" |
43 | |
44 | #include <cassert> |
45 | #include <map> |
46 | #include <memory> |
47 | #include <vector> |
48 | |
49 | class Array; |
50 | class Gfx; |
51 | class GfxFont; |
52 | class PDFRectangle; |
53 | class GfxShading; |
54 | class OutputDev; |
55 | class GfxState; |
56 | class GfxResources; |
57 | class GfxSeparationColorSpace; |
58 | |
59 | class Matrix |
60 | { |
61 | public: |
62 | double m[6]; |
63 | |
64 | void init(double xx, double yx, double xy, double yy, double x0, double y0) |
65 | { |
66 | m[0] = xx; |
67 | m[1] = yx; |
68 | m[2] = xy; |
69 | m[3] = yy; |
70 | m[4] = x0; |
71 | m[5] = y0; |
72 | } |
73 | bool invertTo(Matrix *other) const; |
74 | void translate(double tx, double ty); |
75 | void scale(double sx, double sy); |
76 | void transform(double x, double y, double *tx, double *ty) const; |
77 | double determinant() const { return m[0] * m[3] - m[1] * m[2]; } |
78 | double norm() const; |
79 | }; |
80 | |
81 | //------------------------------------------------------------------------ |
82 | // GfxBlendMode |
83 | //------------------------------------------------------------------------ |
84 | |
85 | enum GfxBlendMode |
86 | { |
87 | gfxBlendNormal, |
88 | gfxBlendMultiply, |
89 | gfxBlendScreen, |
90 | gfxBlendOverlay, |
91 | gfxBlendDarken, |
92 | gfxBlendLighten, |
93 | gfxBlendColorDodge, |
94 | gfxBlendColorBurn, |
95 | gfxBlendHardLight, |
96 | gfxBlendSoftLight, |
97 | gfxBlendDifference, |
98 | gfxBlendExclusion, |
99 | gfxBlendHue, |
100 | gfxBlendSaturation, |
101 | gfxBlendColor, |
102 | gfxBlendLuminosity |
103 | }; |
104 | |
105 | //------------------------------------------------------------------------ |
106 | // GfxColorComp |
107 | //------------------------------------------------------------------------ |
108 | |
109 | // 16.16 fixed point color component |
110 | typedef int GfxColorComp; |
111 | |
112 | #define gfxColorComp1 0x10000 |
113 | |
114 | static inline GfxColorComp dblToCol(double x) |
115 | { |
116 | return (GfxColorComp)(x * gfxColorComp1); |
117 | } |
118 | |
119 | static inline double colToDbl(GfxColorComp x) |
120 | { |
121 | return (double)x / (double)gfxColorComp1; |
122 | } |
123 | |
124 | static inline unsigned char dblToByte(double x) |
125 | { |
126 | return static_cast<unsigned char>(x * 255.0); |
127 | } |
128 | |
129 | static inline double byteToDbl(unsigned char x) |
130 | { |
131 | return (double)x / (double)255.0; |
132 | } |
133 | |
134 | static inline GfxColorComp byteToCol(unsigned char x) |
135 | { |
136 | // (x / 255) << 16 = (0.0000000100000001... * x) << 16 |
137 | // = ((x << 8) + (x) + (x >> 8) + ...) << 16 |
138 | // = (x << 8) + (x) + (x >> 7) |
139 | // [for rounding] |
140 | return (GfxColorComp)((x << 8) + x + (x >> 7)); |
141 | } |
142 | |
143 | static inline unsigned char colToByte(GfxColorComp x) |
144 | { |
145 | // 255 * x + 0.5 = 256 * x - x + 0x8000 |
146 | return (unsigned char)(((x << 8) - x + 0x8000) >> 16); |
147 | } |
148 | |
149 | static inline unsigned short colToShort(GfxColorComp x) |
150 | { |
151 | return (unsigned short)(x); |
152 | } |
153 | |
154 | //------------------------------------------------------------------------ |
155 | // GfxColor |
156 | //------------------------------------------------------------------------ |
157 | |
158 | #define gfxColorMaxComps funcMaxOutputs |
159 | |
160 | struct GfxColor |
161 | { |
162 | GfxColorComp c[gfxColorMaxComps]; |
163 | }; |
164 | |
165 | static inline void clearGfxColor(GfxColor *gfxColor) |
166 | { |
167 | memset(s: gfxColor->c, c: 0, n: sizeof(GfxColorComp) * gfxColorMaxComps); |
168 | } |
169 | |
170 | //------------------------------------------------------------------------ |
171 | // GfxGray |
172 | //------------------------------------------------------------------------ |
173 | |
174 | typedef GfxColorComp GfxGray; |
175 | |
176 | //------------------------------------------------------------------------ |
177 | // GfxRGB |
178 | //------------------------------------------------------------------------ |
179 | |
180 | struct GfxRGB |
181 | { |
182 | GfxColorComp r, g, b; |
183 | |
184 | bool operator==(GfxRGB other) const { return r == other.r && g == other.g && b == other.b; } |
185 | }; |
186 | |
187 | //------------------------------------------------------------------------ |
188 | // GfxCMYK |
189 | //------------------------------------------------------------------------ |
190 | |
191 | struct GfxCMYK |
192 | { |
193 | GfxColorComp c, m, y, k; |
194 | }; |
195 | |
196 | //------------------------------------------------------------------------ |
197 | // GfxColorSpace |
198 | //------------------------------------------------------------------------ |
199 | |
200 | // NB: The nGfxColorSpaceModes constant and the gfxColorSpaceModeNames |
201 | // array defined in GfxState.cc must match this enum. |
202 | enum GfxColorSpaceMode |
203 | { |
204 | csDeviceGray, |
205 | csCalGray, |
206 | csDeviceRGB, |
207 | csCalRGB, |
208 | csDeviceCMYK, |
209 | csLab, |
210 | csICCBased, |
211 | csIndexed, |
212 | csSeparation, |
213 | csDeviceN, |
214 | csPattern |
215 | }; |
216 | |
217 | // This shall hold a cmsHPROFILE handle. |
218 | // Only use the make_GfxLCMSProfilePtr function to construct this pointer, |
219 | // to ensure that the resources are properly released after usage. |
220 | typedef std::shared_ptr<void> GfxLCMSProfilePtr; |
221 | |
222 | #ifdef USE_CMS |
223 | GfxLCMSProfilePtr POPPLER_PRIVATE_EXPORT make_GfxLCMSProfilePtr(void *profile); |
224 | #endif |
225 | |
226 | // wrapper of cmsHTRANSFORM to copy |
227 | class GfxColorTransform |
228 | { |
229 | public: |
230 | void doTransform(void *in, void *out, unsigned int size); |
231 | // transformA should be a cmsHTRANSFORM |
232 | GfxColorTransform(void *transformA, int cmsIntent, unsigned int inputPixelType, unsigned int transformPixelType); |
233 | ~GfxColorTransform(); |
234 | GfxColorTransform(const GfxColorTransform &) = delete; |
235 | GfxColorTransform &operator=(const GfxColorTransform &) = delete; |
236 | int getIntent() const { return cmsIntent; } |
237 | int getInputPixelType() const { return inputPixelType; } |
238 | int getTransformPixelType() const { return transformPixelType; } |
239 | |
240 | private: |
241 | GfxColorTransform() { } |
242 | void *transform; |
243 | int cmsIntent; |
244 | unsigned int inputPixelType; |
245 | unsigned int transformPixelType; |
246 | }; |
247 | |
248 | class POPPLER_PRIVATE_EXPORT GfxColorSpace |
249 | { |
250 | public: |
251 | GfxColorSpace(); |
252 | virtual ~GfxColorSpace(); |
253 | |
254 | GfxColorSpace(const GfxColorSpace &) = delete; |
255 | GfxColorSpace &operator=(const GfxColorSpace &other) = delete; |
256 | |
257 | virtual GfxColorSpace *copy() const = 0; |
258 | virtual GfxColorSpaceMode getMode() const = 0; |
259 | |
260 | // Construct a color space. Returns nullptr if unsuccessful. |
261 | static GfxColorSpace *parse(GfxResources *res, Object *csObj, OutputDev *out, GfxState *state, int recursion = 0); |
262 | |
263 | // Convert to gray, RGB, or CMYK. |
264 | virtual void getGray(const GfxColor *color, GfxGray *gray) const = 0; |
265 | virtual void getRGB(const GfxColor *color, GfxRGB *rgb) const = 0; |
266 | virtual void getCMYK(const GfxColor *color, GfxCMYK *cmyk) const = 0; |
267 | virtual void getDeviceN(const GfxColor *color, GfxColor *deviceN) const = 0; |
268 | virtual void getGrayLine(unsigned char * /*in*/, unsigned char * /*out*/, int /*length*/) { error(category: errInternal, pos: -1, msg: "GfxColorSpace::getGrayLine this should not happen" ); } |
269 | virtual void getRGBLine(unsigned char * /*in*/, unsigned int * /*out*/, int /*length*/) { error(category: errInternal, pos: -1, msg: "GfxColorSpace::getRGBLine (first variant) this should not happen" ); } |
270 | virtual void getRGBLine(unsigned char * /*in*/, unsigned char * /*out*/, int /*length*/) { error(category: errInternal, pos: -1, msg: "GfxColorSpace::getRGBLine (second variant) this should not happen" ); } |
271 | virtual void getRGBXLine(unsigned char * /*in*/, unsigned char * /*out*/, int /*length*/) { error(category: errInternal, pos: -1, msg: "GfxColorSpace::getRGBXLine this should not happen" ); } |
272 | virtual void getCMYKLine(unsigned char * /*in*/, unsigned char * /*out*/, int /*length*/) { error(category: errInternal, pos: -1, msg: "GfxColorSpace::getCMYKLine this should not happen" ); } |
273 | virtual void getDeviceNLine(unsigned char * /*in*/, unsigned char * /*out*/, int /*length*/) { error(category: errInternal, pos: -1, msg: "GfxColorSpace::getDeviceNLine this should not happen" ); } |
274 | |
275 | // create mapping for spot colorants |
276 | virtual void createMapping(std::vector<GfxSeparationColorSpace *> *separationList, int maxSepComps); |
277 | int *getMapping() const { return mapping; } |
278 | |
279 | // Does this ColorSpace support getRGBLine? |
280 | virtual bool useGetRGBLine() const { return false; } |
281 | // Does this ColorSpace support getGrayLine? |
282 | virtual bool useGetGrayLine() const { return false; } |
283 | // Does this ColorSpace support getCMYKLine? |
284 | virtual bool useGetCMYKLine() const { return false; } |
285 | // Does this ColorSpace support getDeviceNLine? |
286 | virtual bool useGetDeviceNLine() const { return false; } |
287 | |
288 | // Return the number of color components. |
289 | virtual int getNComps() const = 0; |
290 | |
291 | // Get this color space's default color. |
292 | virtual void getDefaultColor(GfxColor *color) const = 0; |
293 | |
294 | // Return the default ranges for each component, assuming an image |
295 | // with a max pixel value of <maxImgPixel>. |
296 | virtual void getDefaultRanges(double *decodeLow, double *decodeRange, int maxImgPixel) const; |
297 | |
298 | // Returns true if painting operations in this color space never |
299 | // mark the page (e.g., the "None" colorant). |
300 | virtual bool isNonMarking() const { return false; } |
301 | |
302 | // Return the color space's overprint mask. |
303 | unsigned int getOverprintMask() const { return overprintMask; } |
304 | |
305 | // Return the number of color space modes |
306 | static int getNumColorSpaceModes(); |
307 | |
308 | // Return the name of the <idx>th color space mode. |
309 | static const char *getColorSpaceModeName(int idx); |
310 | |
311 | protected: |
312 | unsigned int overprintMask; |
313 | int *mapping; |
314 | }; |
315 | |
316 | //------------------------------------------------------------------------ |
317 | // GfxDeviceGrayColorSpace |
318 | //------------------------------------------------------------------------ |
319 | |
320 | class POPPLER_PRIVATE_EXPORT GfxDeviceGrayColorSpace : public GfxColorSpace |
321 | { |
322 | public: |
323 | GfxDeviceGrayColorSpace(); |
324 | ~GfxDeviceGrayColorSpace() override; |
325 | GfxColorSpace *copy() const override; |
326 | GfxColorSpaceMode getMode() const override { return csDeviceGray; } |
327 | |
328 | void getGray(const GfxColor *color, GfxGray *gray) const override; |
329 | void getRGB(const GfxColor *color, GfxRGB *rgb) const override; |
330 | void getCMYK(const GfxColor *color, GfxCMYK *cmyk) const override; |
331 | void getDeviceN(const GfxColor *color, GfxColor *deviceN) const override; |
332 | void getGrayLine(unsigned char *in, unsigned char *out, int length) override; |
333 | void getRGBLine(unsigned char *in, unsigned int *out, int length) override; |
334 | void getRGBLine(unsigned char *in, unsigned char *out, int length) override; |
335 | void getRGBXLine(unsigned char *in, unsigned char *out, int length) override; |
336 | void getCMYKLine(unsigned char *in, unsigned char *out, int length) override; |
337 | void getDeviceNLine(unsigned char *in, unsigned char *out, int length) override; |
338 | |
339 | bool useGetRGBLine() const override { return true; } |
340 | bool useGetGrayLine() const override { return true; } |
341 | bool useGetCMYKLine() const override { return true; } |
342 | bool useGetDeviceNLine() const override { return true; } |
343 | |
344 | int getNComps() const override { return 1; } |
345 | void getDefaultColor(GfxColor *color) const override; |
346 | |
347 | private: |
348 | }; |
349 | |
350 | //------------------------------------------------------------------------ |
351 | // GfxCalGrayColorSpace |
352 | //------------------------------------------------------------------------ |
353 | |
354 | class GfxCalGrayColorSpace : public GfxColorSpace |
355 | { |
356 | public: |
357 | GfxCalGrayColorSpace(); |
358 | ~GfxCalGrayColorSpace() override; |
359 | GfxColorSpace *copy() const override; |
360 | GfxColorSpaceMode getMode() const override { return csCalGray; } |
361 | |
362 | // Construct a CalGray color space. Returns nullptr if unsuccessful. |
363 | static GfxColorSpace *parse(Array *arr, GfxState *state); |
364 | |
365 | void getGray(const GfxColor *color, GfxGray *gray) const override; |
366 | void getRGB(const GfxColor *color, GfxRGB *rgb) const override; |
367 | void getCMYK(const GfxColor *color, GfxCMYK *cmyk) const override; |
368 | void getDeviceN(const GfxColor *color, GfxColor *deviceN) const override; |
369 | |
370 | int getNComps() const override { return 1; } |
371 | void getDefaultColor(GfxColor *color) const override; |
372 | |
373 | // CalGray-specific access. |
374 | double getWhiteX() const { return whiteX; } |
375 | double getWhiteY() const { return whiteY; } |
376 | double getWhiteZ() const { return whiteZ; } |
377 | double getBlackX() const { return blackX; } |
378 | double getBlackY() const { return blackY; } |
379 | double getBlackZ() const { return blackZ; } |
380 | double getGamma() const { return gamma; } |
381 | |
382 | private: |
383 | double whiteX, whiteY, whiteZ; // white point |
384 | double blackX, blackY, blackZ; // black point |
385 | double gamma; // gamma value |
386 | void getXYZ(const GfxColor *color, double *pX, double *pY, double *pZ) const; |
387 | #ifdef USE_CMS |
388 | std::shared_ptr<GfxColorTransform> transform; |
389 | #endif |
390 | }; |
391 | |
392 | //------------------------------------------------------------------------ |
393 | // GfxDeviceRGBColorSpace |
394 | //------------------------------------------------------------------------ |
395 | |
396 | class POPPLER_PRIVATE_EXPORT GfxDeviceRGBColorSpace : public GfxColorSpace |
397 | { |
398 | public: |
399 | GfxDeviceRGBColorSpace(); |
400 | ~GfxDeviceRGBColorSpace() override; |
401 | GfxColorSpace *copy() const override; |
402 | GfxColorSpaceMode getMode() const override { return csDeviceRGB; } |
403 | |
404 | void getGray(const GfxColor *color, GfxGray *gray) const override; |
405 | void getRGB(const GfxColor *color, GfxRGB *rgb) const override; |
406 | void getCMYK(const GfxColor *color, GfxCMYK *cmyk) const override; |
407 | void getDeviceN(const GfxColor *color, GfxColor *deviceN) const override; |
408 | void getGrayLine(unsigned char *in, unsigned char *out, int length) override; |
409 | void getRGBLine(unsigned char *in, unsigned int *out, int length) override; |
410 | void getRGBLine(unsigned char *in, unsigned char *out, int length) override; |
411 | void getRGBXLine(unsigned char *in, unsigned char *out, int length) override; |
412 | void getCMYKLine(unsigned char *in, unsigned char *out, int length) override; |
413 | void getDeviceNLine(unsigned char *in, unsigned char *out, int length) override; |
414 | |
415 | bool useGetRGBLine() const override { return true; } |
416 | bool useGetGrayLine() const override { return true; } |
417 | bool useGetCMYKLine() const override { return true; } |
418 | bool useGetDeviceNLine() const override { return true; } |
419 | |
420 | int getNComps() const override { return 3; } |
421 | void getDefaultColor(GfxColor *color) const override; |
422 | |
423 | private: |
424 | }; |
425 | |
426 | //------------------------------------------------------------------------ |
427 | // GfxCalRGBColorSpace |
428 | //------------------------------------------------------------------------ |
429 | |
430 | class GfxCalRGBColorSpace : public GfxColorSpace |
431 | { |
432 | public: |
433 | GfxCalRGBColorSpace(); |
434 | ~GfxCalRGBColorSpace() override; |
435 | GfxColorSpace *copy() const override; |
436 | GfxColorSpaceMode getMode() const override { return csCalRGB; } |
437 | |
438 | // Construct a CalRGB color space. Returns nullptr if unsuccessful. |
439 | static GfxColorSpace *parse(Array *arr, GfxState *state); |
440 | |
441 | void getGray(const GfxColor *color, GfxGray *gray) const override; |
442 | void getRGB(const GfxColor *color, GfxRGB *rgb) const override; |
443 | void getCMYK(const GfxColor *color, GfxCMYK *cmyk) const override; |
444 | void getDeviceN(const GfxColor *color, GfxColor *deviceN) const override; |
445 | |
446 | int getNComps() const override { return 3; } |
447 | void getDefaultColor(GfxColor *color) const override; |
448 | |
449 | // CalRGB-specific access. |
450 | double getWhiteX() const { return whiteX; } |
451 | double getWhiteY() const { return whiteY; } |
452 | double getWhiteZ() const { return whiteZ; } |
453 | double getBlackX() const { return blackX; } |
454 | double getBlackY() const { return blackY; } |
455 | double getBlackZ() const { return blackZ; } |
456 | double getGammaR() const { return gammaR; } |
457 | double getGammaG() const { return gammaG; } |
458 | double getGammaB() const { return gammaB; } |
459 | const double *getMatrix() const { return mat; } |
460 | |
461 | private: |
462 | double whiteX, whiteY, whiteZ; // white point |
463 | double blackX, blackY, blackZ; // black point |
464 | double gammaR, gammaG, gammaB; // gamma values |
465 | double mat[9]; // ABC -> XYZ transform matrix |
466 | void getXYZ(const GfxColor *color, double *pX, double *pY, double *pZ) const; |
467 | #ifdef USE_CMS |
468 | std::shared_ptr<GfxColorTransform> transform; |
469 | #endif |
470 | }; |
471 | |
472 | //------------------------------------------------------------------------ |
473 | // GfxDeviceCMYKColorSpace |
474 | //------------------------------------------------------------------------ |
475 | |
476 | class POPPLER_PRIVATE_EXPORT GfxDeviceCMYKColorSpace : public GfxColorSpace |
477 | { |
478 | public: |
479 | GfxDeviceCMYKColorSpace(); |
480 | ~GfxDeviceCMYKColorSpace() override; |
481 | GfxColorSpace *copy() const override; |
482 | GfxColorSpaceMode getMode() const override { return csDeviceCMYK; } |
483 | |
484 | void getGray(const GfxColor *color, GfxGray *gray) const override; |
485 | void getRGB(const GfxColor *color, GfxRGB *rgb) const override; |
486 | void getCMYK(const GfxColor *color, GfxCMYK *cmyk) const override; |
487 | void getDeviceN(const GfxColor *color, GfxColor *deviceN) const override; |
488 | void getRGBLine(unsigned char *in, unsigned int *out, int length) override; |
489 | void getRGBLine(unsigned char *, unsigned char *out, int length) override; |
490 | void getRGBXLine(unsigned char *in, unsigned char *out, int length) override; |
491 | void getCMYKLine(unsigned char *in, unsigned char *out, int length) override; |
492 | void getDeviceNLine(unsigned char *in, unsigned char *out, int length) override; |
493 | bool useGetRGBLine() const override { return true; } |
494 | bool useGetCMYKLine() const override { return true; } |
495 | bool useGetDeviceNLine() const override { return true; } |
496 | |
497 | int getNComps() const override { return 4; } |
498 | void getDefaultColor(GfxColor *color) const override; |
499 | |
500 | private: |
501 | }; |
502 | |
503 | //------------------------------------------------------------------------ |
504 | // GfxLabColorSpace |
505 | //------------------------------------------------------------------------ |
506 | |
507 | class GfxLabColorSpace : public GfxColorSpace |
508 | { |
509 | public: |
510 | GfxLabColorSpace(); |
511 | ~GfxLabColorSpace() override; |
512 | GfxColorSpace *copy() const override; |
513 | GfxColorSpaceMode getMode() const override { return csLab; } |
514 | |
515 | // Construct a Lab color space. Returns nullptr if unsuccessful. |
516 | static GfxColorSpace *parse(Array *arr, GfxState *state); |
517 | |
518 | void getGray(const GfxColor *color, GfxGray *gray) const override; |
519 | void getRGB(const GfxColor *color, GfxRGB *rgb) const override; |
520 | void getCMYK(const GfxColor *color, GfxCMYK *cmyk) const override; |
521 | void getDeviceN(const GfxColor *color, GfxColor *deviceN) const override; |
522 | |
523 | int getNComps() const override { return 3; } |
524 | void getDefaultColor(GfxColor *color) const override; |
525 | |
526 | void getDefaultRanges(double *decodeLow, double *decodeRange, int maxImgPixel) const override; |
527 | |
528 | // Lab-specific access. |
529 | double getWhiteX() const { return whiteX; } |
530 | double getWhiteY() const { return whiteY; } |
531 | double getWhiteZ() const { return whiteZ; } |
532 | double getBlackX() const { return blackX; } |
533 | double getBlackY() const { return blackY; } |
534 | double getBlackZ() const { return blackZ; } |
535 | double getAMin() const { return aMin; } |
536 | double getAMax() const { return aMax; } |
537 | double getBMin() const { return bMin; } |
538 | double getBMax() const { return bMax; } |
539 | |
540 | private: |
541 | double whiteX, whiteY, whiteZ; // white point |
542 | double blackX, blackY, blackZ; // black point |
543 | double aMin, aMax, bMin, bMax; // range for the a and b components |
544 | void getXYZ(const GfxColor *color, double *pX, double *pY, double *pZ) const; |
545 | #ifdef USE_CMS |
546 | std::shared_ptr<GfxColorTransform> transform; |
547 | #endif |
548 | }; |
549 | |
550 | //------------------------------------------------------------------------ |
551 | // GfxICCBasedColorSpace |
552 | //------------------------------------------------------------------------ |
553 | |
554 | class POPPLER_PRIVATE_EXPORT GfxICCBasedColorSpace : public GfxColorSpace |
555 | { |
556 | public: |
557 | GfxICCBasedColorSpace(int nCompsA, GfxColorSpace *altA, const Ref *iccProfileStreamA); |
558 | ~GfxICCBasedColorSpace() override; |
559 | GfxColorSpace *copy() const override; |
560 | GfxColorSpaceMode getMode() const override { return csICCBased; } |
561 | |
562 | // Construct an ICCBased color space. Returns nullptr if unsuccessful. |
563 | static GfxColorSpace *parse(Array *arr, OutputDev *out, GfxState *state, int recursion); |
564 | |
565 | void getGray(const GfxColor *color, GfxGray *gray) const override; |
566 | void getRGB(const GfxColor *color, GfxRGB *rgb) const override; |
567 | void getCMYK(const GfxColor *color, GfxCMYK *cmyk) const override; |
568 | void getDeviceN(const GfxColor *color, GfxColor *deviceN) const override; |
569 | void getRGBLine(unsigned char *in, unsigned int *out, int length) override; |
570 | void getRGBLine(unsigned char *in, unsigned char *out, int length) override; |
571 | void getRGBXLine(unsigned char *in, unsigned char *out, int length) override; |
572 | void getCMYKLine(unsigned char *in, unsigned char *out, int length) override; |
573 | void getDeviceNLine(unsigned char *in, unsigned char *out, int length) override; |
574 | |
575 | bool useGetRGBLine() const override; |
576 | bool useGetCMYKLine() const override; |
577 | bool useGetDeviceNLine() const override; |
578 | |
579 | int getNComps() const override { return nComps; } |
580 | void getDefaultColor(GfxColor *color) const override; |
581 | |
582 | void getDefaultRanges(double *decodeLow, double *decodeRange, int maxImgPixel) const override; |
583 | |
584 | // ICCBased-specific access. |
585 | GfxColorSpace *getAlt() { return alt; } |
586 | Ref getRef() { return iccProfileStream; } |
587 | #ifdef USE_CMS |
588 | char *getPostScriptCSA(); |
589 | void buildTransforms(GfxState *state); |
590 | void setProfile(GfxLCMSProfilePtr &profileA) { profile = profileA; } |
591 | GfxLCMSProfilePtr getProfile() { return profile; } |
592 | #endif |
593 | |
594 | private: |
595 | int nComps; // number of color components (1, 3, or 4) |
596 | GfxColorSpace *alt; // alternate color space |
597 | double rangeMin[4]; // min values for each component |
598 | double rangeMax[4]; // max values for each component |
599 | Ref iccProfileStream; // the ICC profile |
600 | #ifdef USE_CMS |
601 | GfxLCMSProfilePtr profile; |
602 | char *psCSA; |
603 | int getIntent() { return (transform != nullptr) ? transform->getIntent() : 0; } |
604 | std::shared_ptr<GfxColorTransform> transform; |
605 | std::shared_ptr<GfxColorTransform> lineTransform; // color transform for line |
606 | mutable std::map<unsigned int, unsigned int> cmsCache; |
607 | #endif |
608 | }; |
609 | //------------------------------------------------------------------------ |
610 | // GfxIndexedColorSpace |
611 | //------------------------------------------------------------------------ |
612 | |
613 | class GfxIndexedColorSpace : public GfxColorSpace |
614 | { |
615 | public: |
616 | GfxIndexedColorSpace(GfxColorSpace *baseA, int indexHighA); |
617 | ~GfxIndexedColorSpace() override; |
618 | GfxColorSpace *copy() const override; |
619 | GfxColorSpaceMode getMode() const override { return csIndexed; } |
620 | |
621 | // Construct an Indexed color space. Returns nullptr if unsuccessful. |
622 | static GfxColorSpace *parse(GfxResources *res, Array *arr, OutputDev *out, GfxState *state, int recursion); |
623 | |
624 | void getGray(const GfxColor *color, GfxGray *gray) const override; |
625 | void getRGB(const GfxColor *color, GfxRGB *rgb) const override; |
626 | void getCMYK(const GfxColor *color, GfxCMYK *cmyk) const override; |
627 | void getDeviceN(const GfxColor *color, GfxColor *deviceN) const override; |
628 | void getRGBLine(unsigned char *in, unsigned int *out, int length) override; |
629 | void getRGBLine(unsigned char *in, unsigned char *out, int length) override; |
630 | void getRGBXLine(unsigned char *in, unsigned char *out, int length) override; |
631 | void getCMYKLine(unsigned char *in, unsigned char *out, int length) override; |
632 | void getDeviceNLine(unsigned char *in, unsigned char *out, int length) override; |
633 | |
634 | bool useGetRGBLine() const override { return true; } |
635 | bool useGetCMYKLine() const override { return true; } |
636 | bool useGetDeviceNLine() const override { return true; } |
637 | |
638 | int getNComps() const override { return 1; } |
639 | void getDefaultColor(GfxColor *color) const override; |
640 | |
641 | void getDefaultRanges(double *decodeLow, double *decodeRange, int maxImgPixel) const override; |
642 | |
643 | // Indexed-specific access. |
644 | GfxColorSpace *getBase() { return base; } |
645 | int getIndexHigh() const { return indexHigh; } |
646 | unsigned char *getLookup() { return lookup; } |
647 | GfxColor *mapColorToBase(const GfxColor *color, GfxColor *baseColor) const; |
648 | unsigned int getOverprintMask() const { return base->getOverprintMask(); } |
649 | void createMapping(std::vector<GfxSeparationColorSpace *> *separationList, int maxSepComps) override { base->createMapping(separationList, maxSepComps); } |
650 | |
651 | private: |
652 | GfxColorSpace *base; // base color space |
653 | int indexHigh; // max pixel value |
654 | unsigned char *lookup; // lookup table |
655 | }; |
656 | |
657 | //------------------------------------------------------------------------ |
658 | // GfxSeparationColorSpace |
659 | //------------------------------------------------------------------------ |
660 | |
661 | class GfxSeparationColorSpace : public GfxColorSpace |
662 | { |
663 | public: |
664 | GfxSeparationColorSpace(GooString *nameA, GfxColorSpace *altA, Function *funcA); |
665 | ~GfxSeparationColorSpace() override; |
666 | GfxColorSpace *copy() const override; |
667 | GfxColorSpaceMode getMode() const override { return csSeparation; } |
668 | |
669 | // Construct a Separation color space. Returns nullptr if unsuccessful. |
670 | static GfxColorSpace *parse(GfxResources *res, Array *arr, OutputDev *out, GfxState *state, int recursion); |
671 | |
672 | void getGray(const GfxColor *color, GfxGray *gray) const override; |
673 | void getRGB(const GfxColor *color, GfxRGB *rgb) const override; |
674 | void getCMYK(const GfxColor *color, GfxCMYK *cmyk) const override; |
675 | void getDeviceN(const GfxColor *color, GfxColor *deviceN) const override; |
676 | |
677 | void createMapping(std::vector<GfxSeparationColorSpace *> *separationList, int maxSepComps) override; |
678 | |
679 | int getNComps() const override { return 1; } |
680 | void getDefaultColor(GfxColor *color) const override; |
681 | |
682 | bool isNonMarking() const override { return nonMarking; } |
683 | |
684 | // Separation-specific access. |
685 | const GooString *getName() const { return name; } |
686 | GfxColorSpace *getAlt() { return alt; } |
687 | const Function *getFunc() const { return func; } |
688 | |
689 | private: |
690 | GfxSeparationColorSpace(GooString *nameA, GfxColorSpace *altA, Function *funcA, bool nonMarkingA, unsigned int overprintMaskA, int *mappingA); |
691 | |
692 | GooString *name; // colorant name |
693 | GfxColorSpace *alt; // alternate color space |
694 | Function *func; // tint transform (into alternate color space) |
695 | bool nonMarking; |
696 | }; |
697 | |
698 | //------------------------------------------------------------------------ |
699 | // GfxDeviceNColorSpace |
700 | //------------------------------------------------------------------------ |
701 | |
702 | class GfxDeviceNColorSpace : public GfxColorSpace |
703 | { |
704 | public: |
705 | GfxDeviceNColorSpace(int nCompsA, std::vector<std::string> &&namesA, GfxColorSpace *alt, Function *func, std::vector<GfxSeparationColorSpace *> *sepsCS); |
706 | ~GfxDeviceNColorSpace() override; |
707 | GfxColorSpace *copy() const override; |
708 | GfxColorSpaceMode getMode() const override { return csDeviceN; } |
709 | |
710 | // Construct a DeviceN color space. Returns nullptr if unsuccessful. |
711 | static GfxColorSpace *parse(GfxResources *res, Array *arr, OutputDev *out, GfxState *state, int recursion); |
712 | |
713 | void getGray(const GfxColor *color, GfxGray *gray) const override; |
714 | void getRGB(const GfxColor *color, GfxRGB *rgb) const override; |
715 | void getCMYK(const GfxColor *color, GfxCMYK *cmyk) const override; |
716 | void getDeviceN(const GfxColor *color, GfxColor *deviceN) const override; |
717 | |
718 | void createMapping(std::vector<GfxSeparationColorSpace *> *separationList, int maxSepComps) override; |
719 | |
720 | int getNComps() const override { return nComps; } |
721 | void getDefaultColor(GfxColor *color) const override; |
722 | |
723 | bool isNonMarking() const override { return nonMarking; } |
724 | |
725 | // DeviceN-specific access. |
726 | const std::string &getColorantName(int i) const { return names[i]; } |
727 | GfxColorSpace *getAlt() { return alt; } |
728 | const Function *getTintTransformFunc() const { return func; } |
729 | |
730 | private: |
731 | GfxDeviceNColorSpace(int nCompsA, const std::vector<std::string> &namesA, GfxColorSpace *alt, Function *func, std::vector<GfxSeparationColorSpace *> *sepsCSA, int *mappingA, bool nonMarkingA, unsigned int overprintMaskA); |
732 | |
733 | const int nComps; // number of components |
734 | const std::vector<std::string> names; // colorant names |
735 | GfxColorSpace *alt; // alternate color space |
736 | Function *func; // tint transform (into alternate color space) |
737 | bool nonMarking; |
738 | std::vector<GfxSeparationColorSpace *> *sepsCS; // list of separation cs for spot colorants; |
739 | }; |
740 | |
741 | //------------------------------------------------------------------------ |
742 | // GfxPatternColorSpace |
743 | //------------------------------------------------------------------------ |
744 | |
745 | class GfxPatternColorSpace : public GfxColorSpace |
746 | { |
747 | public: |
748 | explicit GfxPatternColorSpace(GfxColorSpace *underA); |
749 | ~GfxPatternColorSpace() override; |
750 | GfxColorSpace *copy() const override; |
751 | GfxColorSpaceMode getMode() const override { return csPattern; } |
752 | |
753 | // Construct a Pattern color space. Returns nullptr if unsuccessful. |
754 | static GfxColorSpace *parse(GfxResources *res, Array *arr, OutputDev *out, GfxState *state, int recursion); |
755 | |
756 | void getGray(const GfxColor *color, GfxGray *gray) const override; |
757 | void getRGB(const GfxColor *color, GfxRGB *rgb) const override; |
758 | void getCMYK(const GfxColor *color, GfxCMYK *cmyk) const override; |
759 | void getDeviceN(const GfxColor *color, GfxColor *deviceN) const override; |
760 | |
761 | int getNComps() const override { return 0; } |
762 | void getDefaultColor(GfxColor *color) const override; |
763 | |
764 | // Pattern-specific access. |
765 | GfxColorSpace *getUnder() { return under; } |
766 | |
767 | private: |
768 | GfxColorSpace *under; // underlying color space (for uncolored |
769 | // patterns) |
770 | }; |
771 | |
772 | //------------------------------------------------------------------------ |
773 | // GfxPattern |
774 | //------------------------------------------------------------------------ |
775 | |
776 | class GfxPattern |
777 | { |
778 | public: |
779 | GfxPattern(int typeA, int patternRefNumA); |
780 | virtual ~GfxPattern(); |
781 | |
782 | GfxPattern(const GfxPattern &) = delete; |
783 | GfxPattern &operator=(const GfxPattern &other) = delete; |
784 | |
785 | static GfxPattern *parse(GfxResources *res, Object *obj, OutputDev *out, GfxState *state, int patternRefNum); |
786 | |
787 | virtual GfxPattern *copy() const = 0; |
788 | |
789 | int getType() const { return type; } |
790 | |
791 | int getPatternRefNum() const { return patternRefNum; } |
792 | |
793 | private: |
794 | int type; |
795 | int patternRefNum; |
796 | }; |
797 | |
798 | //------------------------------------------------------------------------ |
799 | // GfxTilingPattern |
800 | //------------------------------------------------------------------------ |
801 | |
802 | class GfxTilingPattern : public GfxPattern |
803 | { |
804 | public: |
805 | static GfxTilingPattern *parse(Object *patObj, int patternRefNum); |
806 | ~GfxTilingPattern() override; |
807 | |
808 | GfxPattern *copy() const override; |
809 | |
810 | int getPaintType() const { return paintType; } |
811 | int getTilingType() const { return tilingType; } |
812 | const double *getBBox() const { return bbox; } |
813 | double getXStep() const { return xStep; } |
814 | double getYStep() const { return yStep; } |
815 | Dict *getResDict() { return resDict.isDict() ? resDict.getDict() : (Dict *)nullptr; } |
816 | const double *getMatrix() const { return matrix; } |
817 | Object *getContentStream() { return &contentStream; } |
818 | |
819 | private: |
820 | GfxTilingPattern(int paintTypeA, int tilingTypeA, const double *bboxA, double xStepA, double yStepA, const Object *resDictA, const double *matrixA, const Object *contentStreamA, int patternRefNumA); |
821 | |
822 | int paintType; |
823 | int tilingType; |
824 | double bbox[4]; |
825 | double xStep, yStep; |
826 | Object resDict; |
827 | double matrix[6]; |
828 | Object contentStream; |
829 | }; |
830 | |
831 | //------------------------------------------------------------------------ |
832 | // GfxShadingPattern |
833 | //------------------------------------------------------------------------ |
834 | |
835 | class GfxShadingPattern : public GfxPattern |
836 | { |
837 | public: |
838 | static GfxShadingPattern *parse(GfxResources *res, Object *patObj, OutputDev *out, GfxState *state, int patternRefNum); |
839 | ~GfxShadingPattern() override; |
840 | |
841 | GfxPattern *copy() const override; |
842 | |
843 | GfxShading *getShading() { return shading; } |
844 | const double *getMatrix() const { return matrix; } |
845 | |
846 | private: |
847 | GfxShadingPattern(GfxShading *shadingA, const double *matrixA, int patternRefNumA); |
848 | |
849 | GfxShading *shading; |
850 | double matrix[6]; |
851 | }; |
852 | |
853 | //------------------------------------------------------------------------ |
854 | // GfxShading |
855 | //------------------------------------------------------------------------ |
856 | |
857 | class POPPLER_PRIVATE_EXPORT GfxShading |
858 | { |
859 | public: |
860 | explicit GfxShading(int typeA); |
861 | explicit GfxShading(const GfxShading *shading); |
862 | virtual ~GfxShading(); |
863 | |
864 | GfxShading(const GfxShading &) = delete; |
865 | GfxShading &operator=(const GfxShading &other) = delete; |
866 | |
867 | static GfxShading *parse(GfxResources *res, Object *obj, OutputDev *out, GfxState *state); |
868 | |
869 | virtual GfxShading *copy() const = 0; |
870 | |
871 | int getType() const { return type; } |
872 | GfxColorSpace *getColorSpace() { return colorSpace; } |
873 | const GfxColor *getBackground() const { return &background; } |
874 | bool getHasBackground() const { return hasBackground; } |
875 | void getBBox(double *xMinA, double *yMinA, double *xMaxA, double *yMaxA) const |
876 | { |
877 | *xMinA = bbox_xMin; |
878 | *yMinA = bbox_yMin; |
879 | *xMaxA = bbox_xMax; |
880 | *yMaxA = bbox_yMax; |
881 | } |
882 | bool getHasBBox() const { return hasBBox; } |
883 | |
884 | protected: |
885 | virtual bool init(GfxResources *res, Dict *dict, OutputDev *out, GfxState *state); |
886 | |
887 | // 1: Function-based shading |
888 | // 2: Axial shading |
889 | // 3: Radial shading |
890 | // 4: Free-form Gouraud-shaded triangle mesh |
891 | // 5: Lattice-form Gouraud-shaded triangle mesh |
892 | // 6: Coons patch mesh |
893 | // 7: Tensor-product patch mesh |
894 | int type; |
895 | bool hasBackground; |
896 | bool hasBBox; |
897 | GfxColorSpace *colorSpace; |
898 | GfxColor background; |
899 | double bbox_xMin, bbox_yMin, bbox_xMax, bbox_yMax; |
900 | }; |
901 | |
902 | //------------------------------------------------------------------------ |
903 | // GfxUnivariateShading |
904 | //------------------------------------------------------------------------ |
905 | |
906 | class POPPLER_PRIVATE_EXPORT GfxUnivariateShading : public GfxShading |
907 | { |
908 | public: |
909 | GfxUnivariateShading(int typeA, double t0A, double t1A, std::vector<std::unique_ptr<Function>> &&funcsA, bool extend0A, bool extend1A); |
910 | explicit GfxUnivariateShading(const GfxUnivariateShading *shading); |
911 | ~GfxUnivariateShading() override; |
912 | |
913 | double getDomain0() const { return t0; } |
914 | double getDomain1() const { return t1; } |
915 | bool getExtend0() const { return extend0; } |
916 | bool getExtend1() const { return extend1; } |
917 | int getNFuncs() const { return funcs.size(); } |
918 | const Function *getFunc(int i) const { return funcs[i].get(); } |
919 | // returns the nComps of the shading |
920 | // i.e. how many positions of color have been set |
921 | int getColor(double t, GfxColor *color); |
922 | |
923 | void setupCache(const Matrix *ctm, double xMin, double yMin, double xMax, double yMax); |
924 | |
925 | virtual void getParameterRange(double *lower, double *upper, double xMin, double yMin, double xMax, double yMax) = 0; |
926 | |
927 | virtual double getDistance(double sMin, double sMax) const = 0; |
928 | |
929 | protected: |
930 | bool init(GfxResources *res, Dict *dict, OutputDev *out, GfxState *state) override; |
931 | |
932 | private: |
933 | double t0, t1; |
934 | std::vector<std::unique_ptr<Function>> funcs; |
935 | bool extend0, extend1; |
936 | |
937 | int cacheSize, lastMatch; |
938 | double *cacheBounds; |
939 | double *cacheCoeff; |
940 | double *cacheValues; |
941 | }; |
942 | |
943 | //------------------------------------------------------------------------ |
944 | // GfxFunctionShading |
945 | //------------------------------------------------------------------------ |
946 | |
947 | class POPPLER_PRIVATE_EXPORT GfxFunctionShading : public GfxShading |
948 | { |
949 | public: |
950 | GfxFunctionShading(double x0A, double y0A, double x1A, double y1A, const double *matrixA, std::vector<std::unique_ptr<Function>> &&funcsA); |
951 | explicit GfxFunctionShading(const GfxFunctionShading *shading); |
952 | ~GfxFunctionShading() override; |
953 | |
954 | static GfxFunctionShading *parse(GfxResources *res, Dict *dict, OutputDev *out, GfxState *state); |
955 | |
956 | GfxShading *copy() const override; |
957 | |
958 | void getDomain(double *x0A, double *y0A, double *x1A, double *y1A) const |
959 | { |
960 | *x0A = x0; |
961 | *y0A = y0; |
962 | *x1A = x1; |
963 | *y1A = y1; |
964 | } |
965 | const double *getMatrix() const { return matrix; } |
966 | int getNFuncs() const { return funcs.size(); } |
967 | const Function *getFunc(int i) const { return funcs[i].get(); } |
968 | void getColor(double x, double y, GfxColor *color) const; |
969 | |
970 | protected: |
971 | bool init(GfxResources *res, Dict *dict, OutputDev *out, GfxState *state) override; |
972 | |
973 | private: |
974 | double x0, y0, x1, y1; |
975 | double matrix[6]; |
976 | std::vector<std::unique_ptr<Function>> funcs; |
977 | }; |
978 | |
979 | //------------------------------------------------------------------------ |
980 | // GfxAxialShading |
981 | //------------------------------------------------------------------------ |
982 | |
983 | class GfxAxialShading : public GfxUnivariateShading |
984 | { |
985 | public: |
986 | GfxAxialShading(double x0A, double y0A, double x1A, double y1A, double t0A, double t1A, std::vector<std::unique_ptr<Function>> &&funcsA, bool extend0A, bool extend1A); |
987 | explicit GfxAxialShading(const GfxAxialShading *shading); |
988 | ~GfxAxialShading() override; |
989 | |
990 | static GfxAxialShading *parse(GfxResources *res, Dict *dict, OutputDev *out, GfxState *state); |
991 | |
992 | GfxShading *copy() const override; |
993 | |
994 | void getCoords(double *x0A, double *y0A, double *x1A, double *y1A) const |
995 | { |
996 | *x0A = x0; |
997 | *y0A = y0; |
998 | *x1A = x1; |
999 | *y1A = y1; |
1000 | } |
1001 | |
1002 | void getParameterRange(double *lower, double *upper, double xMin, double yMin, double xMax, double yMax) override; |
1003 | |
1004 | double getDistance(double sMin, double sMax) const override; |
1005 | |
1006 | private: |
1007 | double x0, y0, x1, y1; |
1008 | }; |
1009 | |
1010 | //------------------------------------------------------------------------ |
1011 | // GfxRadialShading |
1012 | //------------------------------------------------------------------------ |
1013 | |
1014 | class GfxRadialShading : public GfxUnivariateShading |
1015 | { |
1016 | public: |
1017 | GfxRadialShading(double x0A, double y0A, double r0A, double x1A, double y1A, double r1A, double t0A, double t1A, std::vector<std::unique_ptr<Function>> &&funcsA, bool extend0A, bool extend1A); |
1018 | explicit GfxRadialShading(const GfxRadialShading *shading); |
1019 | ~GfxRadialShading() override; |
1020 | |
1021 | static GfxRadialShading *parse(GfxResources *res, Dict *dict, OutputDev *out, GfxState *state); |
1022 | |
1023 | GfxShading *copy() const override; |
1024 | |
1025 | void getCoords(double *x0A, double *y0A, double *r0A, double *x1A, double *y1A, double *r1A) const |
1026 | { |
1027 | *x0A = x0; |
1028 | *y0A = y0; |
1029 | *r0A = r0; |
1030 | *x1A = x1; |
1031 | *y1A = y1; |
1032 | *r1A = r1; |
1033 | } |
1034 | |
1035 | void getParameterRange(double *lower, double *upper, double xMin, double yMin, double xMax, double yMax) override; |
1036 | |
1037 | double getDistance(double sMin, double sMax) const override; |
1038 | |
1039 | private: |
1040 | double x0, y0, r0, x1, y1, r1; |
1041 | }; |
1042 | |
1043 | //------------------------------------------------------------------------ |
1044 | // GfxGouraudTriangleShading |
1045 | //------------------------------------------------------------------------ |
1046 | |
1047 | struct GfxGouraudVertex |
1048 | { |
1049 | double x, y; |
1050 | GfxColor color; |
1051 | }; |
1052 | |
1053 | class POPPLER_PRIVATE_EXPORT GfxGouraudTriangleShading : public GfxShading |
1054 | { |
1055 | public: |
1056 | GfxGouraudTriangleShading(int typeA, GfxGouraudVertex *verticesA, int nVerticesA, int (*trianglesA)[3], int nTrianglesA, std::vector<std::unique_ptr<Function>> &&funcsA); |
1057 | explicit GfxGouraudTriangleShading(const GfxGouraudTriangleShading *shading); |
1058 | ~GfxGouraudTriangleShading() override; |
1059 | |
1060 | static GfxGouraudTriangleShading *parse(GfxResources *res, int typeA, Dict *dict, Stream *str, OutputDev *out, GfxState *state); |
1061 | |
1062 | GfxShading *copy() const override; |
1063 | |
1064 | int getNTriangles() const { return nTriangles; } |
1065 | |
1066 | bool isParameterized() const { return !funcs.empty(); } |
1067 | |
1068 | /** |
1069 | * @precondition isParameterized() == true |
1070 | */ |
1071 | double getParameterDomainMin() const |
1072 | { |
1073 | assert(isParameterized()); |
1074 | return funcs[0]->getDomainMin(i: 0); |
1075 | } |
1076 | |
1077 | /** |
1078 | * @precondition isParameterized() == true |
1079 | */ |
1080 | double getParameterDomainMax() const |
1081 | { |
1082 | assert(isParameterized()); |
1083 | return funcs[0]->getDomainMax(i: 0); |
1084 | } |
1085 | |
1086 | /** |
1087 | * @precondition isParameterized() == false |
1088 | */ |
1089 | void getTriangle(int i, double *x0, double *y0, GfxColor *color0, double *x1, double *y1, GfxColor *color1, double *x2, double *y2, GfxColor *color2); |
1090 | |
1091 | /** |
1092 | * Variant for functions. |
1093 | * |
1094 | * @precondition isParameterized() == true |
1095 | */ |
1096 | void getTriangle(int i, double *x0, double *y0, double *color0, double *x1, double *y1, double *color1, double *x2, double *y2, double *color2); |
1097 | |
1098 | void getParameterizedColor(double t, GfxColor *color) const; |
1099 | |
1100 | protected: |
1101 | bool init(GfxResources *res, Dict *dict, OutputDev *out, GfxState *state) override; |
1102 | |
1103 | private: |
1104 | GfxGouraudVertex *vertices; |
1105 | int nVertices; |
1106 | int (*triangles)[3]; |
1107 | int nTriangles; |
1108 | std::vector<std::unique_ptr<Function>> funcs; |
1109 | }; |
1110 | |
1111 | //------------------------------------------------------------------------ |
1112 | // GfxPatchMeshShading |
1113 | //------------------------------------------------------------------------ |
1114 | |
1115 | /** |
1116 | * A tensor product cubic bezier patch consisting of 4x4 points and 4 color |
1117 | * values. |
1118 | * |
1119 | * See the Shading Type 7 specifications. Note that Shading Type 6 is also |
1120 | * represented using GfxPatch. |
1121 | */ |
1122 | struct GfxPatch |
1123 | { |
1124 | /** |
1125 | * Represents a single color value for the patch. |
1126 | */ |
1127 | struct ColorValue |
1128 | { |
1129 | /** |
1130 | * For parameterized patches, only element 0 is valid; it contains |
1131 | * the single parameter. |
1132 | * |
1133 | * For non-parameterized patches, c contains all color components |
1134 | * as decoded from the input stream. In this case, you will need to |
1135 | * use dblToCol() before assigning them to GfxColor. |
1136 | */ |
1137 | double c[gfxColorMaxComps]; |
1138 | }; |
1139 | |
1140 | double x[4][4]; |
1141 | double y[4][4]; |
1142 | ColorValue color[2][2]; |
1143 | }; |
1144 | |
1145 | class POPPLER_PRIVATE_EXPORT GfxPatchMeshShading : public GfxShading |
1146 | { |
1147 | public: |
1148 | GfxPatchMeshShading(int typeA, GfxPatch *patchesA, int nPatchesA, std::vector<std::unique_ptr<Function>> &&funcsA); |
1149 | explicit GfxPatchMeshShading(const GfxPatchMeshShading *shading); |
1150 | ~GfxPatchMeshShading() override; |
1151 | |
1152 | static GfxPatchMeshShading *parse(GfxResources *res, int typeA, Dict *dict, Stream *str, OutputDev *out, GfxState *state); |
1153 | |
1154 | GfxShading *copy() const override; |
1155 | |
1156 | int getNPatches() const { return nPatches; } |
1157 | const GfxPatch *getPatch(int i) const { return &patches[i]; } |
1158 | |
1159 | bool isParameterized() const { return !funcs.empty(); } |
1160 | |
1161 | /** |
1162 | * @precondition isParameterized() == true |
1163 | */ |
1164 | double getParameterDomainMin() const |
1165 | { |
1166 | assert(isParameterized()); |
1167 | return funcs[0]->getDomainMin(i: 0); |
1168 | } |
1169 | |
1170 | /** |
1171 | * @precondition isParameterized() == true |
1172 | */ |
1173 | double getParameterDomainMax() const |
1174 | { |
1175 | assert(isParameterized()); |
1176 | return funcs[0]->getDomainMax(i: 0); |
1177 | } |
1178 | |
1179 | void getParameterizedColor(double t, GfxColor *color) const; |
1180 | |
1181 | protected: |
1182 | bool init(GfxResources *res, Dict *dict, OutputDev *out, GfxState *state) override; |
1183 | |
1184 | private: |
1185 | GfxPatch *patches; |
1186 | int nPatches; |
1187 | std::vector<std::unique_ptr<Function>> funcs; |
1188 | }; |
1189 | |
1190 | //------------------------------------------------------------------------ |
1191 | // GfxImageColorMap |
1192 | //------------------------------------------------------------------------ |
1193 | |
1194 | class POPPLER_PRIVATE_EXPORT GfxImageColorMap |
1195 | { |
1196 | public: |
1197 | // Constructor. |
1198 | GfxImageColorMap(int bitsA, Object *decode, GfxColorSpace *colorSpaceA); |
1199 | |
1200 | // Destructor. |
1201 | ~GfxImageColorMap(); |
1202 | |
1203 | GfxImageColorMap(const GfxImageColorMap &) = delete; |
1204 | GfxImageColorMap &operator=(const GfxImageColorMap &) = delete; |
1205 | |
1206 | // Return a copy of this color map. |
1207 | GfxImageColorMap *copy() const { return new GfxImageColorMap(this); } |
1208 | |
1209 | // Is color map valid? |
1210 | bool isOk() const { return ok; } |
1211 | |
1212 | // Get the color space. |
1213 | GfxColorSpace *getColorSpace() { return colorSpace; } |
1214 | |
1215 | // Get stream decoding info. |
1216 | int getNumPixelComps() const { return nComps; } |
1217 | int getBits() const { return bits; } |
1218 | |
1219 | // Get decode table. |
1220 | double getDecodeLow(int i) const { return decodeLow[i]; } |
1221 | double getDecodeHigh(int i) const { return decodeLow[i] + decodeRange[i]; } |
1222 | |
1223 | bool useRGBLine() const { return (colorSpace2 && colorSpace2->useGetRGBLine()) || (!colorSpace2 && colorSpace->useGetRGBLine()); } |
1224 | bool useCMYKLine() const { return (colorSpace2 && colorSpace2->useGetCMYKLine()) || (!colorSpace2 && colorSpace->useGetCMYKLine()); } |
1225 | bool useDeviceNLine() const { return (colorSpace2 && colorSpace2->useGetDeviceNLine()) || (!colorSpace2 && colorSpace->useGetDeviceNLine()); } |
1226 | |
1227 | // Convert an image pixel to a color. |
1228 | void getGray(const unsigned char *x, GfxGray *gray); |
1229 | void getRGB(const unsigned char *x, GfxRGB *rgb); |
1230 | void getRGBLine(unsigned char *in, unsigned int *out, int length); |
1231 | void getRGBLine(unsigned char *in, unsigned char *out, int length); |
1232 | void getRGBXLine(unsigned char *in, unsigned char *out, int length); |
1233 | void getGrayLine(unsigned char *in, unsigned char *out, int length); |
1234 | void getCMYKLine(unsigned char *in, unsigned char *out, int length); |
1235 | void getDeviceNLine(unsigned char *in, unsigned char *out, int length); |
1236 | void getCMYK(const unsigned char *x, GfxCMYK *cmyk); |
1237 | void getDeviceN(const unsigned char *x, GfxColor *deviceN); |
1238 | void getColor(const unsigned char *x, GfxColor *color); |
1239 | |
1240 | // Matte color ops |
1241 | void setMatteColor(const GfxColor *color) |
1242 | { |
1243 | useMatte = true; |
1244 | matteColor = *color; |
1245 | } |
1246 | const GfxColor *getMatteColor() const { return (useMatte) ? &matteColor : nullptr; } |
1247 | |
1248 | private: |
1249 | explicit GfxImageColorMap(const GfxImageColorMap *colorMap); |
1250 | |
1251 | GfxColorSpace *colorSpace; // the image color space |
1252 | int bits; // bits per component |
1253 | int nComps; // number of components in a pixel |
1254 | GfxColorSpace *colorSpace2; // secondary color space |
1255 | int nComps2; // number of components in colorSpace2 |
1256 | GfxColorComp * // lookup table |
1257 | lookup[gfxColorMaxComps]; |
1258 | GfxColorComp * // optimized case lookup table |
1259 | lookup2[gfxColorMaxComps]; |
1260 | unsigned char *byte_lookup; |
1261 | double // minimum values for each component |
1262 | decodeLow[gfxColorMaxComps]; |
1263 | double // max - min value for each component |
1264 | decodeRange[gfxColorMaxComps]; |
1265 | bool useMatte; |
1266 | GfxColor matteColor; |
1267 | bool ok; |
1268 | }; |
1269 | |
1270 | //------------------------------------------------------------------------ |
1271 | // GfxSubpath and GfxPath |
1272 | //------------------------------------------------------------------------ |
1273 | |
1274 | class GfxSubpath |
1275 | { |
1276 | public: |
1277 | // Constructor. |
1278 | GfxSubpath(double x1, double y1); |
1279 | |
1280 | // Destructor. |
1281 | ~GfxSubpath(); |
1282 | |
1283 | GfxSubpath(const GfxSubpath &) = delete; |
1284 | GfxSubpath &operator=(const GfxSubpath &) = delete; |
1285 | |
1286 | // Copy. |
1287 | GfxSubpath *copy() const { return new GfxSubpath(this); } |
1288 | |
1289 | // Get points. |
1290 | int getNumPoints() const { return n; } |
1291 | double getX(int i) const { return x[i]; } |
1292 | double getY(int i) const { return y[i]; } |
1293 | bool getCurve(int i) const { return curve[i]; } |
1294 | |
1295 | void setX(int i, double a) { x[i] = a; } |
1296 | void setY(int i, double a) { y[i] = a; } |
1297 | |
1298 | // Get last point. |
1299 | double getLastX() const { return x[n - 1]; } |
1300 | double getLastY() const { return y[n - 1]; } |
1301 | |
1302 | // Add a line segment. |
1303 | void lineTo(double x1, double y1); |
1304 | |
1305 | // Add a Bezier curve. |
1306 | void curveTo(double x1, double y1, double x2, double y2, double x3, double y3); |
1307 | |
1308 | // Close the subpath. |
1309 | void close(); |
1310 | bool isClosed() const { return closed; } |
1311 | |
1312 | // Add (<dx>, <dy>) to each point in the subpath. |
1313 | void offset(double dx, double dy); |
1314 | |
1315 | private: |
1316 | double *x, *y; // points |
1317 | bool *curve; // curve[i] => point i is a control point |
1318 | // for a Bezier curve |
1319 | int n; // number of points |
1320 | int size; // size of x/y arrays |
1321 | bool closed; // set if path is closed |
1322 | |
1323 | explicit GfxSubpath(const GfxSubpath *subpath); |
1324 | }; |
1325 | |
1326 | class POPPLER_PRIVATE_EXPORT GfxPath |
1327 | { |
1328 | public: |
1329 | // Constructor. |
1330 | GfxPath(); |
1331 | |
1332 | // Destructor. |
1333 | ~GfxPath(); |
1334 | |
1335 | GfxPath(const GfxPath &) = delete; |
1336 | GfxPath &operator=(const GfxPath &) = delete; |
1337 | |
1338 | // Copy. |
1339 | GfxPath *copy() const { return new GfxPath(justMoved, firstX, firstY, subpaths, n, size); } |
1340 | |
1341 | // Is there a current point? |
1342 | bool isCurPt() const { return n > 0 || justMoved; } |
1343 | |
1344 | // Is the path non-empty, i.e., is there at least one segment? |
1345 | bool isPath() const { return n > 0; } |
1346 | |
1347 | // Get subpaths. |
1348 | int getNumSubpaths() const { return n; } |
1349 | GfxSubpath *getSubpath(int i) { return subpaths[i]; } |
1350 | const GfxSubpath *getSubpath(int i) const { return subpaths[i]; } |
1351 | |
1352 | // Get last point on last subpath. |
1353 | double getLastX() const { return subpaths[n - 1]->getLastX(); } |
1354 | double getLastY() const { return subpaths[n - 1]->getLastY(); } |
1355 | |
1356 | // Move the current point. |
1357 | void moveTo(double x, double y); |
1358 | |
1359 | // Add a segment to the last subpath. |
1360 | void lineTo(double x, double y); |
1361 | |
1362 | // Add a Bezier curve to the last subpath |
1363 | void curveTo(double x1, double y1, double x2, double y2, double x3, double y3); |
1364 | |
1365 | // Close the last subpath. |
1366 | void close(); |
1367 | |
1368 | // Append <path> to <this>. |
1369 | void append(GfxPath *path); |
1370 | |
1371 | // Add (<dx>, <dy>) to each point in the path. |
1372 | void offset(double dx, double dy); |
1373 | |
1374 | private: |
1375 | bool justMoved; // set if a new subpath was just started |
1376 | double firstX, firstY; // first point in new subpath |
1377 | GfxSubpath **subpaths; // subpaths |
1378 | int n; // number of subpaths |
1379 | int size; // size of subpaths array |
1380 | |
1381 | GfxPath(bool justMoved1, double firstX1, double firstY1, GfxSubpath **subpaths1, int n1, int size1); |
1382 | }; |
1383 | |
1384 | //------------------------------------------------------------------------ |
1385 | // GfxState |
1386 | //------------------------------------------------------------------------ |
1387 | |
1388 | class POPPLER_PRIVATE_EXPORT GfxState |
1389 | { |
1390 | public: |
1391 | /** |
1392 | * When GfxState::getReusablePath() is invoked, the currently active |
1393 | * path is taken per reference and its coordinates can be re-edited. |
1394 | * |
1395 | * A ReusablePathIterator is intended to reduce overhead when the same |
1396 | * path type is used a lot of times, only with different coordinates. It |
1397 | * allows just to update the coordinates (occurring in the same order as |
1398 | * in the original path). |
1399 | */ |
1400 | class ReusablePathIterator |
1401 | { |
1402 | public: |
1403 | /** |
1404 | * Creates the ReusablePathIterator. This should only be done from |
1405 | * GfxState::getReusablePath(). |
1406 | * |
1407 | * @param path the path as it is used so far. Changing this path, |
1408 | * deleting it or starting a new path from scratch will most likely |
1409 | * invalidate the iterator (and may cause serious problems). Make |
1410 | * sure the path's memory structure is not changed during the |
1411 | * lifetime of the ReusablePathIterator. |
1412 | */ |
1413 | explicit ReusablePathIterator(GfxPath *path); |
1414 | |
1415 | /** |
1416 | * Returns true if and only if the current iterator position is |
1417 | * beyond the last valid point. |
1418 | * |
1419 | * A call to setCoord() will be undefined. |
1420 | */ |
1421 | bool isEnd() const; |
1422 | |
1423 | /** |
1424 | * Advances the iterator. |
1425 | */ |
1426 | void next(); |
1427 | |
1428 | /** |
1429 | * Updates the coordinates associated to the current iterator |
1430 | * position. |
1431 | */ |
1432 | void setCoord(double x, double y); |
1433 | |
1434 | /** |
1435 | * Resets the iterator. |
1436 | */ |
1437 | void reset(); |
1438 | |
1439 | private: |
1440 | GfxPath *path; |
1441 | int subPathOff; |
1442 | |
1443 | int coordOff; |
1444 | int numCoords; |
1445 | |
1446 | GfxSubpath *curSubPath; |
1447 | }; |
1448 | |
1449 | // Construct a default GfxState, for a device with resolution <hDPI> |
1450 | // x <vDPI>, page box <pageBox>, page rotation <rotateA>, and |
1451 | // coordinate system specified by <upsideDown>. |
1452 | GfxState(double hDPIA, double vDPIA, const PDFRectangle *pageBox, int rotateA, bool upsideDown); |
1453 | |
1454 | // Destructor. |
1455 | ~GfxState(); |
1456 | |
1457 | GfxState(const GfxState &) = delete; |
1458 | GfxState &operator=(const GfxState &) = delete; |
1459 | |
1460 | // Copy. |
1461 | GfxState *copy(bool copyPath = false) const { return new GfxState(this, copyPath); } |
1462 | |
1463 | // Accessors. |
1464 | double getHDPI() const { return hDPI; } |
1465 | double getVDPI() const { return vDPI; } |
1466 | const double *getCTM() const { return ctm; } |
1467 | void getCTM(Matrix *m) const { memcpy(dest: m->m, src: ctm, n: sizeof m->m); } |
1468 | double getX1() const { return px1; } |
1469 | double getY1() const { return py1; } |
1470 | double getX2() const { return px2; } |
1471 | double getY2() const { return py2; } |
1472 | double getPageWidth() const { return pageWidth; } |
1473 | double getPageHeight() const { return pageHeight; } |
1474 | int getRotate() const { return rotate; } |
1475 | const GfxColor *getFillColor() const { return &fillColor; } |
1476 | const GfxColor *getStrokeColor() const { return &strokeColor; } |
1477 | void getFillGray(GfxGray *gray) { fillColorSpace->getGray(color: &fillColor, gray); } |
1478 | void getStrokeGray(GfxGray *gray) { strokeColorSpace->getGray(color: &strokeColor, gray); } |
1479 | void getFillRGB(GfxRGB *rgb) const { fillColorSpace->getRGB(color: &fillColor, rgb); } |
1480 | void getStrokeRGB(GfxRGB *rgb) const { strokeColorSpace->getRGB(color: &strokeColor, rgb); } |
1481 | void getFillCMYK(GfxCMYK *cmyk) { fillColorSpace->getCMYK(color: &fillColor, cmyk); } |
1482 | void getFillDeviceN(GfxColor *deviceN) { fillColorSpace->getDeviceN(color: &fillColor, deviceN); } |
1483 | void getStrokeCMYK(GfxCMYK *cmyk) { strokeColorSpace->getCMYK(color: &strokeColor, cmyk); } |
1484 | void getStrokeDeviceN(GfxColor *deviceN) { strokeColorSpace->getDeviceN(color: &strokeColor, deviceN); } |
1485 | GfxColorSpace *getFillColorSpace() { return fillColorSpace; } |
1486 | GfxColorSpace *getStrokeColorSpace() { return strokeColorSpace; } |
1487 | GfxPattern *getFillPattern() { return fillPattern; } |
1488 | GfxPattern *getStrokePattern() { return strokePattern; } |
1489 | GfxBlendMode getBlendMode() const { return blendMode; } |
1490 | double getFillOpacity() const { return fillOpacity; } |
1491 | double getStrokeOpacity() const { return strokeOpacity; } |
1492 | bool getFillOverprint() const { return fillOverprint; } |
1493 | bool getStrokeOverprint() const { return strokeOverprint; } |
1494 | int getOverprintMode() const { return overprintMode; } |
1495 | Function **getTransfer() { return transfer; } |
1496 | double getLineWidth() const { return lineWidth; } |
1497 | const std::vector<double> &getLineDash(double *start) |
1498 | { |
1499 | *start = lineDashStart; |
1500 | return lineDash; |
1501 | } |
1502 | int getFlatness() const { return flatness; } |
1503 | int getLineJoin() const { return lineJoin; } |
1504 | int getLineCap() const { return lineCap; } |
1505 | double getMiterLimit() const { return miterLimit; } |
1506 | bool getStrokeAdjust() const { return strokeAdjust; } |
1507 | bool getAlphaIsShape() const { return alphaIsShape; } |
1508 | bool getTextKnockout() const { return textKnockout; } |
1509 | const std::shared_ptr<GfxFont> &getFont() const { return font; } |
1510 | double getFontSize() const { return fontSize; } |
1511 | const double *getTextMat() const { return textMat; } |
1512 | double getCharSpace() const { return charSpace; } |
1513 | double getWordSpace() const { return wordSpace; } |
1514 | double getHorizScaling() const { return horizScaling; } |
1515 | double getLeading() const { return leading; } |
1516 | double getRise() const { return rise; } |
1517 | int getRender() const { return render; } |
1518 | const char *getRenderingIntent() const { return renderingIntent; } |
1519 | const GfxPath *getPath() const { return path; } |
1520 | void setPath(GfxPath *pathA); |
1521 | double getCurX() const { return curX; } |
1522 | double getCurY() const { return curY; } |
1523 | void getClipBBox(double *xMin, double *yMin, double *xMax, double *yMax) const |
1524 | { |
1525 | *xMin = clipXMin; |
1526 | *yMin = clipYMin; |
1527 | *xMax = clipXMax; |
1528 | *yMax = clipYMax; |
1529 | } |
1530 | void getUserClipBBox(double *xMin, double *yMin, double *xMax, double *yMax) const; |
1531 | double getLineX() const { return lineX; } |
1532 | double getLineY() const { return lineY; } |
1533 | |
1534 | // Is there a current point/path? |
1535 | bool isCurPt() const { return path->isCurPt(); } |
1536 | bool isPath() const { return path->isPath(); } |
1537 | |
1538 | // Transforms. |
1539 | void transform(double x1, double y1, double *x2, double *y2) const |
1540 | { |
1541 | *x2 = ctm[0] * x1 + ctm[2] * y1 + ctm[4]; |
1542 | *y2 = ctm[1] * x1 + ctm[3] * y1 + ctm[5]; |
1543 | } |
1544 | void transformDelta(double x1, double y1, double *x2, double *y2) const |
1545 | { |
1546 | *x2 = ctm[0] * x1 + ctm[2] * y1; |
1547 | *y2 = ctm[1] * x1 + ctm[3] * y1; |
1548 | } |
1549 | void textTransform(double x1, double y1, double *x2, double *y2) const |
1550 | { |
1551 | *x2 = textMat[0] * x1 + textMat[2] * y1 + textMat[4]; |
1552 | *y2 = textMat[1] * x1 + textMat[3] * y1 + textMat[5]; |
1553 | } |
1554 | void textTransformDelta(double x1, double y1, double *x2, double *y2) const |
1555 | { |
1556 | *x2 = textMat[0] * x1 + textMat[2] * y1; |
1557 | *y2 = textMat[1] * x1 + textMat[3] * y1; |
1558 | } |
1559 | double transformWidth(double w) const; |
1560 | double getTransformedLineWidth() const { return transformWidth(w: lineWidth); } |
1561 | double getTransformedFontSize() const; |
1562 | void getFontTransMat(double *m11, double *m12, double *m21, double *m22) const; |
1563 | |
1564 | // Change state parameters. |
1565 | void setCTM(double a, double b, double c, double d, double e, double f); |
1566 | void concatCTM(double a, double b, double c, double d, double e, double f); |
1567 | void shiftCTMAndClip(double tx, double ty); |
1568 | void setFillColorSpace(GfxColorSpace *colorSpace); |
1569 | void setStrokeColorSpace(GfxColorSpace *colorSpace); |
1570 | void setFillColor(const GfxColor *color) { fillColor = *color; } |
1571 | void setStrokeColor(const GfxColor *color) { strokeColor = *color; } |
1572 | void setFillPattern(GfxPattern *pattern); |
1573 | void setStrokePattern(GfxPattern *pattern); |
1574 | void setBlendMode(GfxBlendMode mode) { blendMode = mode; } |
1575 | void setFillOpacity(double opac) { fillOpacity = opac; } |
1576 | void setStrokeOpacity(double opac) { strokeOpacity = opac; } |
1577 | void setFillOverprint(bool op) { fillOverprint = op; } |
1578 | void setStrokeOverprint(bool op) { strokeOverprint = op; } |
1579 | void setOverprintMode(int op) { overprintMode = op; } |
1580 | void setTransfer(Function **funcs); |
1581 | void setLineWidth(double width) { lineWidth = width; } |
1582 | void setLineDash(std::vector<double> &&dash, double start); |
1583 | void setFlatness(int flatness1) { flatness = flatness1; } |
1584 | void setLineJoin(int lineJoin1) { lineJoin = lineJoin1; } |
1585 | void setLineCap(int lineCap1) { lineCap = lineCap1; } |
1586 | void setMiterLimit(double limit) { miterLimit = limit; } |
1587 | void setStrokeAdjust(bool sa) { strokeAdjust = sa; } |
1588 | void setAlphaIsShape(bool ais) { alphaIsShape = ais; } |
1589 | void setTextKnockout(bool tk) { textKnockout = tk; } |
1590 | void setFont(std::shared_ptr<GfxFont> fontA, double fontSizeA); |
1591 | void setTextMat(double a, double b, double c, double d, double e, double f) |
1592 | { |
1593 | textMat[0] = a; |
1594 | textMat[1] = b; |
1595 | textMat[2] = c; |
1596 | textMat[3] = d; |
1597 | textMat[4] = e; |
1598 | textMat[5] = f; |
1599 | } |
1600 | void setCharSpace(double space) { charSpace = space; } |
1601 | void setWordSpace(double space) { wordSpace = space; } |
1602 | void setHorizScaling(double scale) { horizScaling = 0.01 * scale; } |
1603 | void setLeading(double leadingA) { leading = leadingA; } |
1604 | void setRise(double riseA) { rise = riseA; } |
1605 | void setRender(int renderA) { render = renderA; } |
1606 | void setRenderingIntent(const char *intent) { strncpy(dest: renderingIntent, src: intent, n: 31); } |
1607 | |
1608 | #ifdef USE_CMS |
1609 | void setDisplayProfile(const GfxLCMSProfilePtr &localDisplayProfileA); |
1610 | GfxLCMSProfilePtr getDisplayProfile() { return localDisplayProfile; } |
1611 | std::shared_ptr<GfxColorTransform> getXYZ2DisplayTransform(); |
1612 | int getCmsRenderingIntent(); |
1613 | static GfxLCMSProfilePtr sRGBProfile; |
1614 | #endif |
1615 | |
1616 | void setDefaultGrayColorSpace(GfxColorSpace *cs) { defaultGrayColorSpace = cs; } |
1617 | |
1618 | void setDefaultRGBColorSpace(GfxColorSpace *cs) { defaultRGBColorSpace = cs; } |
1619 | |
1620 | void setDefaultCMYKColorSpace(GfxColorSpace *cs) { defaultCMYKColorSpace = cs; } |
1621 | |
1622 | GfxColorSpace *copyDefaultGrayColorSpace() |
1623 | { |
1624 | if (defaultGrayColorSpace) { |
1625 | return defaultGrayColorSpace->copy(); |
1626 | } |
1627 | return new GfxDeviceGrayColorSpace(); |
1628 | } |
1629 | |
1630 | GfxColorSpace *copyDefaultRGBColorSpace() |
1631 | { |
1632 | if (defaultRGBColorSpace) { |
1633 | return defaultRGBColorSpace->copy(); |
1634 | } |
1635 | return new GfxDeviceRGBColorSpace(); |
1636 | } |
1637 | |
1638 | GfxColorSpace *copyDefaultCMYKColorSpace() |
1639 | { |
1640 | if (defaultCMYKColorSpace) { |
1641 | return defaultCMYKColorSpace->copy(); |
1642 | } |
1643 | return new GfxDeviceCMYKColorSpace(); |
1644 | } |
1645 | |
1646 | // Add to path. |
1647 | void moveTo(double x, double y) { path->moveTo(x: curX = x, y: curY = y); } |
1648 | void lineTo(double x, double y) { path->lineTo(x: curX = x, y: curY = y); } |
1649 | void curveTo(double x1, double y1, double x2, double y2, double x3, double y3) { path->curveTo(x1, y1, x2, y2, x3: curX = x3, y3: curY = y3); } |
1650 | void closePath() |
1651 | { |
1652 | path->close(); |
1653 | curX = path->getLastX(); |
1654 | curY = path->getLastY(); |
1655 | } |
1656 | void clearPath(); |
1657 | |
1658 | // Update clip region. |
1659 | void clip(); |
1660 | void clipToStrokePath(); |
1661 | void clipToRect(double xMin, double yMin, double xMax, double yMax); |
1662 | |
1663 | // Text position. |
1664 | void textSetPos(double tx, double ty) |
1665 | { |
1666 | lineX = tx; |
1667 | lineY = ty; |
1668 | } |
1669 | void textMoveTo(double tx, double ty) |
1670 | { |
1671 | lineX = tx; |
1672 | lineY = ty; |
1673 | textTransform(x1: tx, y1: ty, x2: &curX, y2: &curY); |
1674 | } |
1675 | void textShift(double tx, double ty); |
1676 | void shift(double dx, double dy); |
1677 | |
1678 | // Push/pop GfxState on/off stack. |
1679 | GfxState *save(); |
1680 | GfxState *restore(); |
1681 | bool hasSaves() const { return saved != nullptr; } |
1682 | bool isParentState(GfxState *state) { return saved == state || (saved && saved->isParentState(state)); } |
1683 | |
1684 | // Misc |
1685 | bool parseBlendMode(Object *obj, GfxBlendMode *mode); |
1686 | |
1687 | ReusablePathIterator *getReusablePath() { return new ReusablePathIterator(path); } |
1688 | |
1689 | private: |
1690 | double hDPI, vDPI; // resolution |
1691 | double ctm[6]; // coord transform matrix |
1692 | double px1, py1, px2, py2; // page corners (user coords) |
1693 | double pageWidth, pageHeight; // page size (pixels) |
1694 | int rotate; // page rotation angle |
1695 | |
1696 | GfxColorSpace *fillColorSpace; // fill color space |
1697 | GfxColorSpace *strokeColorSpace; // stroke color space |
1698 | GfxColor fillColor; // fill color |
1699 | GfxColor strokeColor; // stroke color |
1700 | GfxPattern *fillPattern; // fill pattern |
1701 | GfxPattern *strokePattern; // stroke pattern |
1702 | GfxBlendMode blendMode; // transparency blend mode |
1703 | double fillOpacity; // fill opacity |
1704 | double strokeOpacity; // stroke opacity |
1705 | bool fillOverprint; // fill overprint |
1706 | bool strokeOverprint; // stroke overprint |
1707 | int overprintMode; // overprint mode |
1708 | Function *transfer[4]; // transfer function (entries may be: all |
1709 | // nullptr = identity; last three nullptr = |
1710 | // single function; all four non-nullptr = |
1711 | // R,G,B,gray functions) |
1712 | |
1713 | double lineWidth; // line width |
1714 | std::vector<double> lineDash; // line dash |
1715 | double lineDashStart; |
1716 | int flatness; // curve flatness |
1717 | int lineJoin; // line join style |
1718 | int lineCap; // line cap style |
1719 | double miterLimit; // line miter limit |
1720 | bool strokeAdjust; // stroke adjustment |
1721 | bool alphaIsShape; // alpha is shape |
1722 | bool textKnockout; // text knockout |
1723 | |
1724 | std::shared_ptr<GfxFont> font; // font |
1725 | double fontSize; // font size |
1726 | double textMat[6]; // text matrix |
1727 | double charSpace; // character spacing |
1728 | double wordSpace; // word spacing |
1729 | double horizScaling; // horizontal scaling |
1730 | double leading; // text leading |
1731 | double rise; // text rise |
1732 | int render; // text rendering mode |
1733 | |
1734 | GfxPath *path; // array of path elements |
1735 | double curX, curY; // current point (user coords) |
1736 | double lineX, lineY; // start of current text line (text coords) |
1737 | |
1738 | double clipXMin, clipYMin, // bounding box for clip region |
1739 | clipXMax, clipYMax; |
1740 | char renderingIntent[32]; |
1741 | |
1742 | GfxState *saved; // next GfxState on stack |
1743 | |
1744 | GfxState(const GfxState *state, bool copyPath); |
1745 | |
1746 | #ifdef USE_CMS |
1747 | GfxLCMSProfilePtr localDisplayProfile; |
1748 | std::shared_ptr<GfxColorTransform> XYZ2DisplayTransformRelCol; |
1749 | std::shared_ptr<GfxColorTransform> XYZ2DisplayTransformAbsCol; |
1750 | std::shared_ptr<GfxColorTransform> XYZ2DisplayTransformSat; |
1751 | std::shared_ptr<GfxColorTransform> XYZ2DisplayTransformPerc; |
1752 | static GfxLCMSProfilePtr XYZProfile; |
1753 | #endif |
1754 | |
1755 | GfxColorSpace *defaultGrayColorSpace; |
1756 | GfxColorSpace *defaultRGBColorSpace; |
1757 | GfxColorSpace *defaultCMYKColorSpace; |
1758 | }; |
1759 | |
1760 | #endif |
1761 | |