/src/poppler/poppler/Gfx.h
Line | Count | Source |
1 | | //======================================================================== |
2 | | // |
3 | | // Gfx.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 Jonathan Blandford <jrb@redhat.com> |
17 | | // Copyright (C) 2007 Iñigo Martínez <inigomartinez@gmail.com> |
18 | | // Copyright (C) 2008 Brad Hards <bradh@kde.org> |
19 | | // Copyright (C) 2008, 2010 Carlos Garcia Campos <carlosgc@gnome.org> |
20 | | // Copyright (C) 2009-2013, 2017, 2018, 2021, 2024-2026 Albert Astals Cid <aacid@kde.org> |
21 | | // Copyright (C) 2009, 2010, 2012, 2013 Thomas Freitag <Thomas.Freitag@alfa.de> |
22 | | // Copyright (C) 2010 David Benjamin <davidben@mit.edu> |
23 | | // Copyright (C) 2010 Christian Feuersänger <cfeuersaenger@googlemail.com> |
24 | | // Copyright (C) 2013 Fabio D'Urso <fabiodurso@hotmail.it> |
25 | | // Copyright (C) 2018 Klarälvdalens Datakonsult AB, a KDAB Group company, <info@kdab.com>. Work sponsored by the LiMux project of the city of Munich |
26 | | // Copyright (C) 2018 Adam Reichold <adam.reichold@t-online.de> |
27 | | // Copyright (C) 2019, 2022, 2024 Oliver Sander <oliver.sander@tu-dresden.de> |
28 | | // Copyright (C) 2019 Volker Krause <vkrause@kde.org> |
29 | | // Copyright (C) 2026 g10 Code GmbH, Author: Sune Stolborg Vuorela <sune@vuorela.dk> |
30 | | // Copyright (C) 2026 Stefan Brüns <stefan.bruens@rwth-aachen.de> |
31 | | // |
32 | | // To see a description of the changes please see the Changelog file that |
33 | | // came with your tarball or type make ChangeLog if you are building from git |
34 | | // |
35 | | //======================================================================== |
36 | | |
37 | | #ifndef GFX_H |
38 | | #define GFX_H |
39 | | |
40 | | #include "poppler-config.h" |
41 | | #include "poppler_private_export.h" |
42 | | #include "GfxState.h" |
43 | | #include "Object.h" |
44 | | #include "PopplerCache.h" |
45 | | |
46 | | #include <stack> |
47 | | #include <vector> |
48 | | |
49 | | class PDFDoc; |
50 | | class XRef; |
51 | | class Array; |
52 | | class Stream; |
53 | | class Parser; |
54 | | class Dict; |
55 | | class Function; |
56 | | class OutputDev; |
57 | | class GfxFontDict; |
58 | | class GfxFont; |
59 | | class GfxPattern; |
60 | | class GfxTilingPattern; |
61 | | class GfxShadingPattern; |
62 | | class GfxShading; |
63 | | class GfxFunctionShading; |
64 | | class GfxAxialShading; |
65 | | class GfxRadialShading; |
66 | | class GfxGouraudTriangleShading; |
67 | | class GfxPatchMeshShading; |
68 | | struct GfxPatch; |
69 | | class GfxState; |
70 | | struct GfxColor; |
71 | | class GfxColorSpace; |
72 | | class Gfx; |
73 | | class PDFRectangle; |
74 | | class AnnotBorder; |
75 | | class AnnotColor; |
76 | | class Catalog; |
77 | | struct MarkedContentStack; |
78 | | |
79 | | //------------------------------------------------------------------------ |
80 | | |
81 | | enum GfxClipType |
82 | | { |
83 | | clipNone, |
84 | | clipNormal, |
85 | | clipEO |
86 | | }; |
87 | | |
88 | | enum TchkType |
89 | | { |
90 | | tchkBool, // boolean |
91 | | tchkInt, // integer |
92 | | tchkNum, // number (integer or real) |
93 | | tchkString, // string |
94 | | tchkName, // name |
95 | | tchkArray, // array |
96 | | tchkProps, // properties (dictionary or name) |
97 | | tchkSCN, // scn/SCN args (number of name) |
98 | | tchkNone // used to avoid empty initializer lists |
99 | | }; |
100 | | |
101 | 8.40M | #define maxArgs 33 |
102 | | |
103 | | struct Operator |
104 | | { |
105 | | char name[4]; |
106 | | int numArgs; |
107 | | TchkType tchk[maxArgs]; |
108 | | void (Gfx::*func)(Object args[], int numArgs); |
109 | | }; |
110 | | |
111 | | //------------------------------------------------------------------------ |
112 | | |
113 | | class POPPLER_PRIVATE_EXPORT GfxResources |
114 | | { |
115 | | public: |
116 | | GfxResources(XRef *xref, Dict *resDict, GfxResources *nextA); |
117 | | ~GfxResources(); |
118 | | |
119 | | GfxResources(const GfxResources &) = delete; |
120 | | GfxResources &operator=(const GfxResources &other) = delete; |
121 | | |
122 | | std::shared_ptr<GfxFont> lookupFont(std::string_view name); |
123 | | std::shared_ptr<const GfxFont> lookupFont(std::string_view name) const; |
124 | | Object lookupXObject(std::string_view name); |
125 | | Object lookupXObjectNF(std::string_view name); |
126 | | Object lookupMarkedContentNF(std::string_view name); |
127 | | Object lookupColorSpace(std::string_view name); |
128 | | std::unique_ptr<GfxPattern> lookupPattern(std::string_view name, OutputDev *out, GfxState *state); |
129 | | std::unique_ptr<GfxShading> lookupShading(std::string_view name, OutputDev *out, GfxState *state); |
130 | | Object lookupGState(std::string_view name); |
131 | | Object lookupGStateNF(std::string_view name); |
132 | | |
133 | 38.7k | GfxResources *getNext() const { return next; } |
134 | | |
135 | | private: |
136 | | std::shared_ptr<GfxFont> doLookupFont(std::string_view name) const; |
137 | | |
138 | | Ref fontDictRef; |
139 | | mutable std::unique_ptr<GfxFontDict> fonts; |
140 | | Object fontDict; |
141 | | Object xObjDict; |
142 | | Object colorSpaceDict; |
143 | | Object patternDict; |
144 | | Object shadingDict; |
145 | | Object gStateDict; |
146 | | PopplerCache<Ref, Object> gStateCache; |
147 | | XRef *xref; |
148 | | Object propertiesDict; |
149 | | GfxResources *next; |
150 | | }; |
151 | | |
152 | | //------------------------------------------------------------------------ |
153 | | // Gfx |
154 | | //------------------------------------------------------------------------ |
155 | | |
156 | | class POPPLER_PRIVATE_EXPORT Gfx |
157 | | { |
158 | | public: |
159 | | // Constructor for regular output. |
160 | | Gfx(PDFDoc *docA, OutputDev *outA, int pageNum, Dict *resDict, double hDPI, double vDPI, const PDFRectangle &box, const PDFRectangle *cropBox, int rotate, bool (*abortCheckCbkA)(void *data) = nullptr, void *abortCheckCbkDataA = nullptr, |
161 | | XRef *xrefA = nullptr); |
162 | | |
163 | | // Constructor for a sub-page object. |
164 | | Gfx(PDFDoc *docA, OutputDev *outA, Dict *resDict, const PDFRectangle &box, const PDFRectangle *cropBox, bool (*abortCheckCbkA)(void *data) = nullptr, void *abortCheckCbkDataA = nullptr, Gfx *gfxA = nullptr); |
165 | | #if USE_CMS |
166 | | void initDisplayProfile(); |
167 | | #endif |
168 | | ~Gfx(); |
169 | | |
170 | | Gfx(const Gfx &) = delete; |
171 | | Gfx &operator=(const Gfx &other) = delete; |
172 | | |
173 | 11.8k | XRef *getXRef() { return xref; } |
174 | | |
175 | | // Interpret a stream or array of streams. |
176 | | enum class DisplayType |
177 | | { |
178 | | TopLevel, |
179 | | Type3Font, |
180 | | Form |
181 | | }; |
182 | | void display(Object *obj, DisplayType displayType = DisplayType::TopLevel); |
183 | | |
184 | | // Display an annotation, given its appearance (a Form XObject), |
185 | | // border style, and bounding box (in default user space). |
186 | | void drawAnnot(Object *str, AnnotBorder *border, AnnotColor *aColor, double xMin, double yMin, double xMax, double yMax, int rotate); |
187 | | |
188 | | // Save graphics state. |
189 | | void saveState(); |
190 | | |
191 | | // Push a new state guard |
192 | | void pushStateGuard(); |
193 | | |
194 | | // Restore graphics state. |
195 | | void restoreState(); |
196 | | |
197 | | // Pop to state guard and pop guard |
198 | | void popStateGuard(); |
199 | | |
200 | | // Get the current graphics state object. |
201 | 0 | GfxState *getState() { return state; } |
202 | | |
203 | | bool checkTransparencyGroup(Dict *resDict); |
204 | | |
205 | | // if softMask is true backdropColor must not be null |
206 | | void drawForm(Object *str, Dict *resDict, const std::array<double, 6> &matrix, const std::array<double, 4> &bbox, bool transpGroup = false, bool softMask = false, GfxColorSpace *blendingColorSpace = nullptr, bool isolated = false, |
207 | | bool knockout = false, bool alpha = false, Function *transferFunc = nullptr, const GfxColor *backdropColor = nullptr); |
208 | | |
209 | | void pushResources(Dict *resDict); |
210 | | void popResources(); |
211 | | |
212 | | private: |
213 | | PDFDoc *doc; |
214 | | XRef *xref; // the xref table for this PDF file |
215 | | Catalog *catalog; // the Catalog for this PDF file |
216 | | OutputDev *out; // output device |
217 | | bool subPage; // is this a sub-page object? |
218 | | const bool printCommands; // print the drawing commands (for debugging) |
219 | | const bool profileCommands; // profile the drawing commands (for debugging) |
220 | | bool commandAborted; // did the previous command abort the drawing? |
221 | | GfxResources *res; // resource stack |
222 | | int updateLevel; |
223 | | |
224 | | std::stack<DisplayType> displayTypes; |
225 | | std::stack<bool> type3FontIsD1; |
226 | | |
227 | | GfxState *state; // current graphics state |
228 | | int stackHeight; // the height of the current graphics stack |
229 | | std::vector<int> stateGuards; // a stack of state limits; to guard against unmatched pops |
230 | | bool fontChanged; // set if font or text matrix has changed |
231 | | GfxClipType clip; // do a clip? |
232 | | int ignoreUndef; // current BX/EX nesting level |
233 | | std::array<double, 6> baseMatrix; // default matrix for most recent |
234 | | // page/form/pattern |
235 | | int displayDepth; |
236 | | bool ocState; // true if drawing is enabled, false if |
237 | | // disabled |
238 | | |
239 | | MarkedContentStack *mcStack; // current BMC/EMC stack |
240 | | |
241 | | Parser *parser; // parser for page content stream(s) |
242 | | |
243 | | std::set<int> formsDrawing; // the forms/patterns that are being drawn |
244 | | std::set<int> charProcDrawing; // the charProc that are being drawn |
245 | | |
246 | | bool // callback to check for an abort |
247 | | (*abortCheckCbk)(void *data); |
248 | | void *abortCheckCbkData; |
249 | | |
250 | | static const Operator opTab[]; // table of operators |
251 | | |
252 | | void go(DisplayType displayType); |
253 | | void execOp(Object *cmd, Object args[], int numArgs); |
254 | | static const Operator *findOp(const char *name); |
255 | | static bool checkArg(Object *arg, TchkType type); |
256 | | Goffset getPos(); |
257 | | |
258 | | int bottomGuard(); |
259 | | |
260 | | // graphics state operators |
261 | | void opSave(Object args[], int numArgs); |
262 | | void opRestore(Object args[], int numArgs); |
263 | | void opConcat(Object args[], int numArgs); |
264 | | void opSetDash(Object args[], int numArgs); |
265 | | void opSetFlat(Object args[], int numArgs); |
266 | | void opSetLineJoin(Object args[], int numArgs); |
267 | | void opSetLineCap(Object args[], int numArgs); |
268 | | void opSetMiterLimit(Object args[], int numArgs); |
269 | | void opSetLineWidth(Object args[], int numArgs); |
270 | | void opSetExtGState(Object args[], int numArgs); |
271 | | void doSoftMask(Object *str, bool alpha, GfxColorSpace *blendingColorSpace, bool isolated, bool knockout, Function *transferFunc, const GfxColor &backdropColor); |
272 | | void opSetRenderingIntent(Object args[], int numArgs); |
273 | | |
274 | | // color operators |
275 | | void opSetFillGray(Object args[], int numArgs); |
276 | | void opSetStrokeGray(Object args[], int numArgs); |
277 | | void opSetFillCMYKColor(Object args[], int numArgs); |
278 | | void opSetStrokeCMYKColor(Object args[], int numArgs); |
279 | | void opSetFillRGBColor(Object args[], int numArgs); |
280 | | void opSetStrokeRGBColor(Object args[], int numArgs); |
281 | | void opSetFillColorSpace(Object args[], int numArgs); |
282 | | void opSetStrokeColorSpace(Object args[], int numArgs); |
283 | | void opSetFillColor(Object args[], int numArgs); |
284 | | void opSetStrokeColor(Object args[], int numArgs); |
285 | | void opSetFillColorN(Object args[], int numArgs); |
286 | | void opSetStrokeColorN(Object args[], int numArgs); |
287 | | |
288 | | // path segment operators |
289 | | void opMoveTo(Object args[], int numArgs); |
290 | | void opLineTo(Object args[], int numArgs); |
291 | | void opCurveTo(Object args[], int numArgs); |
292 | | void opCurveTo1(Object args[], int numArgs); |
293 | | void opCurveTo2(Object args[], int numArgs); |
294 | | void opRectangle(Object args[], int numArgs); |
295 | | void opClosePath(Object args[], int numArgs); |
296 | | |
297 | | // path painting operators |
298 | | void opEndPath(Object args[], int numArgs); |
299 | | void opStroke(Object args[], int numArgs); |
300 | | void opCloseStroke(Object args[], int numArgs); |
301 | | void opFill(Object args[], int numArgs); |
302 | | void opEOFill(Object args[], int numArgs); |
303 | | void opFillStroke(Object args[], int numArgs); |
304 | | void opCloseFillStroke(Object args[], int numArgs); |
305 | | void opEOFillStroke(Object args[], int numArgs); |
306 | | void opCloseEOFillStroke(Object args[], int numArgs); |
307 | | void doPatternFill(bool eoFill); |
308 | | void doPatternStroke(); |
309 | | void doPatternText(); |
310 | | void doPatternImageMask(Object *ref, Stream *str, int width, int height, bool invert, bool inlineImg); |
311 | | void doTilingPatternFill(GfxTilingPattern *tPat, bool stroke, bool eoFill, bool text); |
312 | | void doShadingPatternFill(GfxShadingPattern *sPat, bool stroke, bool eoFill, bool text); |
313 | | void opShFill(Object args[], int numArgs); |
314 | | void doFunctionShFill(GfxFunctionShading *shading); |
315 | | void doFunctionShFill1(GfxFunctionShading *shading, double x0, double y0, double x1, double y1, GfxColor *colors, int depth); |
316 | | void doAxialShFill(GfxAxialShading *shading); |
317 | | void doRadialShFill(GfxRadialShading *shading); |
318 | | void doGouraudTriangleShFill(GfxGouraudTriangleShading *shading); |
319 | | void gouraudFillTriangle(double x0, double y0, GfxColor *color0, double x1, double y1, GfxColor *color1, double x2, double y2, GfxColor *color2, int nComps, int depth, GfxState::ReusablePathIterator *path); |
320 | | void gouraudFillTriangle(double x0, double y0, double color0, double x1, double y1, double color1, double x2, double y2, double color2, double refineColorThreshold, int depth, GfxGouraudTriangleShading *shading, |
321 | | GfxState::ReusablePathIterator *path); |
322 | | void doPatchMeshShFill(GfxPatchMeshShading *shading); |
323 | | void fillPatch(const GfxPatch *patch, int colorComps, int patchColorComps, double refineColorThreshold, int depth, const GfxPatchMeshShading *shading); |
324 | | void doEndPath(); |
325 | | |
326 | | // path clipping operators |
327 | | void opClip(Object args[], int numArgs); |
328 | | void opEOClip(Object args[], int numArgs); |
329 | | |
330 | | // text object operators |
331 | | void opBeginText(Object args[], int numArgs); |
332 | | void opEndText(Object args[], int numArgs); |
333 | | |
334 | | // text state operators |
335 | | void opSetCharSpacing(Object args[], int numArgs); |
336 | | void opSetFont(Object args[], int numArgs); |
337 | | void opSetTextLeading(Object args[], int numArgs); |
338 | | void opSetTextRender(Object args[], int numArgs); |
339 | | void opSetTextRise(Object args[], int numArgs); |
340 | | void opSetWordSpacing(Object args[], int numArgs); |
341 | | void opSetHorizScaling(Object args[], int numArgs); |
342 | | |
343 | | // text positioning operators |
344 | | void opTextMove(Object args[], int numArgs); |
345 | | void opTextMoveSet(Object args[], int numArgs); |
346 | | void opSetTextMatrix(Object args[], int numArgs); |
347 | | void opTextNextLine(Object args[], int numArgs); |
348 | | |
349 | | // text string operators |
350 | | void opShowText(Object args[], int numArgs); |
351 | | void opMoveShowText(Object args[], int numArgs); |
352 | | void opMoveSetShowText(Object args[], int numArgs); |
353 | | void opShowSpaceText(Object args[], int numArgs); |
354 | | void doShowText(const std::string &s); |
355 | | void doIncCharCount(const std::string &s); |
356 | | |
357 | | // XObject operators |
358 | | void opXObject(Object args[], int numArgs); |
359 | | void doImage(Object *ref, Stream *str, bool inlineImg); |
360 | | void doForm(Object *str); |
361 | | |
362 | | // in-line image operators |
363 | | void opBeginImage(Object args[], int numArgs); |
364 | | std::unique_ptr<Stream> buildImageStream(); |
365 | | void opImageData(Object args[], int numArgs); |
366 | | void opEndImage(Object args[], int numArgs); |
367 | | |
368 | | // type 3 font operators |
369 | | void opSetCharWidth(Object args[], int numArgs); |
370 | | void opSetCacheDevice(Object args[], int numArgs); |
371 | | |
372 | | // compatibility operators |
373 | | void opBeginIgnoreUndef(Object args[], int numArgs); |
374 | | void opEndIgnoreUndef(Object args[], int numArgs); |
375 | | |
376 | | // marked content operators |
377 | | void opBeginMarkedContent(Object args[], int numArgs); |
378 | | void opEndMarkedContent(Object args[], int numArgs); |
379 | | void opMarkPoint(Object args[], int numArgs); |
380 | | GfxState *saveStateStack(); |
381 | | void restoreStateStack(GfxState *oldState); |
382 | | bool contentIsHidden(); |
383 | | void pushMarkedContent(); |
384 | | void popMarkedContent(); |
385 | | }; |
386 | | |
387 | | #endif |