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
49class Array;
50class Gfx;
51class GfxFont;
52class PDFRectangle;
53class GfxShading;
54class OutputDev;
55class GfxState;
56class GfxResources;
57class GfxSeparationColorSpace;
58
59class Matrix
60{
61public:
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
85enum 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
110typedef int GfxColorComp;
111
112#define gfxColorComp1 0x10000
113
114static inline GfxColorComp dblToCol(double x)
115{
116 return (GfxColorComp)(x * gfxColorComp1);
117}
118
119static inline double colToDbl(GfxColorComp x)
120{
121 return (double)x / (double)gfxColorComp1;
122}
123
124static inline unsigned char dblToByte(double x)
125{
126 return static_cast<unsigned char>(x * 255.0);
127}
128
129static inline double byteToDbl(unsigned char x)
130{
131 return (double)x / (double)255.0;
132}
133
134static 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
143static 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
149static inline unsigned short colToShort(GfxColorComp x)
150{
151 return (unsigned short)(x);
152}
153
154//------------------------------------------------------------------------
155// GfxColor
156//------------------------------------------------------------------------
157
158#define gfxColorMaxComps funcMaxOutputs
159
160struct GfxColor
161{
162 GfxColorComp c[gfxColorMaxComps];
163};
164
165static inline void clearGfxColor(GfxColor *gfxColor)
166{
167 memset(s: gfxColor->c, c: 0, n: sizeof(GfxColorComp) * gfxColorMaxComps);
168}
169
170//------------------------------------------------------------------------
171// GfxGray
172//------------------------------------------------------------------------
173
174typedef GfxColorComp GfxGray;
175
176//------------------------------------------------------------------------
177// GfxRGB
178//------------------------------------------------------------------------
179
180struct 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
191struct 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.
202enum 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.
220typedef std::shared_ptr<void> GfxLCMSProfilePtr;
221
222#ifdef USE_CMS
223GfxLCMSProfilePtr POPPLER_PRIVATE_EXPORT make_GfxLCMSProfilePtr(void *profile);
224#endif
225
226// wrapper of cmsHTRANSFORM to copy
227class GfxColorTransform
228{
229public:
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
240private:
241 GfxColorTransform() { }
242 void *transform;
243 int cmsIntent;
244 unsigned int inputPixelType;
245 unsigned int transformPixelType;
246};
247
248class POPPLER_PRIVATE_EXPORT GfxColorSpace
249{
250public:
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
311protected:
312 unsigned int overprintMask;
313 int *mapping;
314};
315
316//------------------------------------------------------------------------
317// GfxDeviceGrayColorSpace
318//------------------------------------------------------------------------
319
320class POPPLER_PRIVATE_EXPORT GfxDeviceGrayColorSpace : public GfxColorSpace
321{
322public:
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
347private:
348};
349
350//------------------------------------------------------------------------
351// GfxCalGrayColorSpace
352//------------------------------------------------------------------------
353
354class GfxCalGrayColorSpace : public GfxColorSpace
355{
356public:
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
382private:
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
396class POPPLER_PRIVATE_EXPORT GfxDeviceRGBColorSpace : public GfxColorSpace
397{
398public:
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
423private:
424};
425
426//------------------------------------------------------------------------
427// GfxCalRGBColorSpace
428//------------------------------------------------------------------------
429
430class GfxCalRGBColorSpace : public GfxColorSpace
431{
432public:
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
461private:
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
476class POPPLER_PRIVATE_EXPORT GfxDeviceCMYKColorSpace : public GfxColorSpace
477{
478public:
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
500private:
501};
502
503//------------------------------------------------------------------------
504// GfxLabColorSpace
505//------------------------------------------------------------------------
506
507class GfxLabColorSpace : public GfxColorSpace
508{
509public:
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
540private:
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
554class POPPLER_PRIVATE_EXPORT GfxICCBasedColorSpace : public GfxColorSpace
555{
556public:
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
594private:
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
613class GfxIndexedColorSpace : public GfxColorSpace
614{
615public:
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
651private:
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
661class GfxSeparationColorSpace : public GfxColorSpace
662{
663public:
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
689private:
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
702class GfxDeviceNColorSpace : public GfxColorSpace
703{
704public:
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
730private:
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
745class GfxPatternColorSpace : public GfxColorSpace
746{
747public:
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
767private:
768 GfxColorSpace *under; // underlying color space (for uncolored
769 // patterns)
770};
771
772//------------------------------------------------------------------------
773// GfxPattern
774//------------------------------------------------------------------------
775
776class GfxPattern
777{
778public:
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
793private:
794 int type;
795 int patternRefNum;
796};
797
798//------------------------------------------------------------------------
799// GfxTilingPattern
800//------------------------------------------------------------------------
801
802class GfxTilingPattern : public GfxPattern
803{
804public:
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
819private:
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
835class GfxShadingPattern : public GfxPattern
836{
837public:
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
846private:
847 GfxShadingPattern(GfxShading *shadingA, const double *matrixA, int patternRefNumA);
848
849 GfxShading *shading;
850 double matrix[6];
851};
852
853//------------------------------------------------------------------------
854// GfxShading
855//------------------------------------------------------------------------
856
857class POPPLER_PRIVATE_EXPORT GfxShading
858{
859public:
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
884protected:
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
906class POPPLER_PRIVATE_EXPORT GfxUnivariateShading : public GfxShading
907{
908public:
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
929protected:
930 bool init(GfxResources *res, Dict *dict, OutputDev *out, GfxState *state) override;
931
932private:
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
947class POPPLER_PRIVATE_EXPORT GfxFunctionShading : public GfxShading
948{
949public:
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
970protected:
971 bool init(GfxResources *res, Dict *dict, OutputDev *out, GfxState *state) override;
972
973private:
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
983class GfxAxialShading : public GfxUnivariateShading
984{
985public:
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
1006private:
1007 double x0, y0, x1, y1;
1008};
1009
1010//------------------------------------------------------------------------
1011// GfxRadialShading
1012//------------------------------------------------------------------------
1013
1014class GfxRadialShading : public GfxUnivariateShading
1015{
1016public:
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
1039private:
1040 double x0, y0, r0, x1, y1, r1;
1041};
1042
1043//------------------------------------------------------------------------
1044// GfxGouraudTriangleShading
1045//------------------------------------------------------------------------
1046
1047struct GfxGouraudVertex
1048{
1049 double x, y;
1050 GfxColor color;
1051};
1052
1053class POPPLER_PRIVATE_EXPORT GfxGouraudTriangleShading : public GfxShading
1054{
1055public:
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
1100protected:
1101 bool init(GfxResources *res, Dict *dict, OutputDev *out, GfxState *state) override;
1102
1103private:
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 */
1122struct 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
1145class POPPLER_PRIVATE_EXPORT GfxPatchMeshShading : public GfxShading
1146{
1147public:
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
1181protected:
1182 bool init(GfxResources *res, Dict *dict, OutputDev *out, GfxState *state) override;
1183
1184private:
1185 GfxPatch *patches;
1186 int nPatches;
1187 std::vector<std::unique_ptr<Function>> funcs;
1188};
1189
1190//------------------------------------------------------------------------
1191// GfxImageColorMap
1192//------------------------------------------------------------------------
1193
1194class POPPLER_PRIVATE_EXPORT GfxImageColorMap
1195{
1196public:
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
1248private:
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
1274class GfxSubpath
1275{
1276public:
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
1315private:
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
1326class POPPLER_PRIVATE_EXPORT GfxPath
1327{
1328public:
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
1374private:
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
1388class POPPLER_PRIVATE_EXPORT GfxState
1389{
1390public:
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
1689private:
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

source code of poppler/poppler/GfxState.h