1//========================================================================
2//
3// OutputDev.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) 2006 Thorkild Stray <thorkild@ifi.uio.no>
18// Copyright (C) 2007 Jeff Muizelaar <jeff@infidigm.net>
19// Copyright (C) 2007, 2011, 2017, 2021, 2023 Adrian Johnson <ajohnson@redneon.com>
20// Copyright (C) 2009-2013, 2015 Thomas Freitag <Thomas.Freitag@alfa.de>
21// Copyright (C) 2009, 2011 Carlos Garcia Campos <carlosgc@gnome.org>
22// Copyright (C) 2009, 2012, 2013, 2018, 2019, 2021 Albert Astals Cid <aacid@kde.org>
23// Copyright (C) 2010 Christian Feuersänger <cfeuersaenger@googlemail.com>
24// Copyright (C) 2012 Fabio D'Urso <fabiodurso@hotmail.it>
25// Copyright (C) 2012 William Bader <williambader@hotmail.com>
26// Copyright (C) 2017, 2018, 2020 Oliver Sander <oliver.sander@tu-dresden.de>
27// 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
28// Copyright (C) 2018 Adam Reichold <adam.reichold@t-online.de>
29// Copyright (C) 2020 Philipp Knechtges <philipp-dev@knechtges.com>
30//
31// To see a description of the changes please see the Changelog file that
32// came with your tarball or type make ChangeLog if you are building from git
33//
34//========================================================================
35
36#ifndef OUTPUTDEV_H
37#define OUTPUTDEV_H
38
39#include "poppler-config.h"
40#include "poppler_private_export.h"
41#include "CharTypes.h"
42#include "Object.h"
43#include "PopplerCache.h"
44#include "ProfileData.h"
45#include "GfxState.h"
46#include <memory>
47#include <unordered_map>
48#include <string>
49
50class Annot;
51class Dict;
52class GooString;
53class Gfx;
54class Stream;
55class Links;
56class AnnotLink;
57class Catalog;
58class Page;
59class Function;
60
61//------------------------------------------------------------------------
62// OutputDev
63//------------------------------------------------------------------------
64
65class POPPLER_PRIVATE_EXPORT OutputDev
66{
67public:
68 // Constructor.
69 OutputDev();
70
71 // Destructor.
72 virtual ~OutputDev();
73
74 //----- get info about output device
75
76 // Does this device use upside-down coordinates?
77 // (Upside-down means (0,0) is the top left corner of the page.)
78 virtual bool upsideDown() = 0;
79
80 // Does this device use drawChar() or drawString()?
81 virtual bool useDrawChar() = 0;
82
83 // Does this device use tilingPatternFill()? If this returns false,
84 // tiling pattern fills will be reduced to a series of other drawing
85 // operations.
86 virtual bool useTilingPatternFill() { return false; }
87
88 // Does this device support specific shading types?
89 // see gouraudTriangleShadedFill() and patchMeshShadedFill()
90 virtual bool useShadedFills(int type) { return false; }
91
92 // Does this device use FillColorStop()?
93 virtual bool useFillColorStop() { return false; }
94
95 // Does this device use drawForm()? If this returns false,
96 // form-type XObjects will be interpreted (i.e., unrolled).
97 virtual bool useDrawForm() { return false; }
98
99 // Does this device use beginType3Char/endType3Char? Otherwise,
100 // text in Type 3 fonts will be drawn with drawChar/drawString.
101 virtual bool interpretType3Chars() = 0;
102
103 // Does this device need non-text content?
104 virtual bool needNonText() { return true; }
105
106 // Does this device require incCharCount to be called for text on
107 // non-shown layers?
108 virtual bool needCharCount() { return false; }
109
110 // Does this device need to clip pages to the crop box even when the
111 // box is the crop box?
112 virtual bool needClipToCropBox() { return false; }
113
114 //----- initialization and control
115
116 // Set default transform matrix.
117 virtual void setDefaultCTM(const double *ctm);
118
119 // Check to see if a page slice should be displayed. If this
120 // returns false, the page display is aborted. Typically, an
121 // OutputDev will use some alternate means to display the page
122 // before returning false.
123 virtual bool checkPageSlice(Page *page, double hDPI, double vDPI, int rotate, bool useMediaBox, bool crop, int sliceX, int sliceY, int sliceW, int sliceH, bool printing, bool (*abortCheckCbk)(void *data) = nullptr,
124 void *abortCheckCbkData = nullptr, bool (*annotDisplayDecideCbk)(Annot *annot, void *user_data) = nullptr, void *annotDisplayDecideCbkData = nullptr)
125 {
126 return true;
127 }
128
129 // Start a page.
130 virtual void startPage(int pageNum, GfxState *state, XRef *xref) { }
131
132 // End a page.
133 virtual void endPage() { }
134
135 // Dump page contents to display.
136 virtual void dump() { }
137
138 virtual void initGfxState(GfxState *state)
139 {
140#ifdef USE_CMS
141 state->setDisplayProfile(displayprofile);
142
143 auto invalidref = Ref::INVALID();
144 if (defaultGrayProfile) {
145 auto cs = new GfxICCBasedColorSpace(1, new GfxDeviceGrayColorSpace(), &invalidref);
146
147 cs->setProfile(defaultGrayProfile);
148 cs->buildTransforms(state); // needs to happen after state->setDisplayProfile has been called
149 state->setDefaultGrayColorSpace(cs);
150 }
151
152 if (defaultRGBProfile) {
153 auto cs = new GfxICCBasedColorSpace(3, new GfxDeviceRGBColorSpace(), &invalidref);
154
155 cs->setProfile(defaultRGBProfile);
156 cs->buildTransforms(state); // needs to happen after state->setDisplayProfile has been called
157 state->setDefaultRGBColorSpace(cs);
158 }
159
160 if (defaultCMYKProfile) {
161 auto cs = new GfxICCBasedColorSpace(4, new GfxDeviceCMYKColorSpace(), &invalidref);
162
163 cs->setProfile(defaultCMYKProfile);
164 cs->buildTransforms(state); // needs to happen after state->setDisplayProfile has been called
165 state->setDefaultCMYKColorSpace(cs);
166 }
167#endif
168 }
169
170 //----- coordinate conversion
171
172 // Convert between device and user coordinates.
173 virtual void cvtDevToUser(double dx, double dy, double *ux, double *uy);
174 virtual void cvtUserToDev(double ux, double uy, int *dx, int *dy);
175
176 const double *getDefCTM() const { return defCTM; }
177 const double *getDefICTM() const { return defICTM; }
178
179 //----- save/restore graphics state
180 virtual void saveState(GfxState * /*state*/) { }
181 virtual void restoreState(GfxState * /*state*/) { }
182
183 //----- update graphics state
184 virtual void updateAll(GfxState *state);
185
186 // Update the Current Transformation Matrix (CTM), i.e., the new matrix
187 // given in m11, ..., m32 is combined with the current value of the CTM.
188 // At the same time, when this method is called, state->getCTM() already
189 // contains the correct new CTM, so one may as well replace the
190 // CTM of the renderer with that.
191 virtual void updateCTM(GfxState * /*state*/, double /*m11*/, double /*m12*/, double /*m21*/, double /*m22*/, double /*m31*/, double /*m32*/) { }
192 virtual void updateLineDash(GfxState * /*state*/) { }
193 virtual void updateFlatness(GfxState * /*state*/) { }
194 virtual void updateLineJoin(GfxState * /*state*/) { }
195 virtual void updateLineCap(GfxState * /*state*/) { }
196 virtual void updateMiterLimit(GfxState * /*state*/) { }
197 virtual void updateLineWidth(GfxState * /*state*/) { }
198 virtual void updateStrokeAdjust(GfxState * /*state*/) { }
199 virtual void updateAlphaIsShape(GfxState * /*state*/) { }
200 virtual void updateTextKnockout(GfxState * /*state*/) { }
201 virtual void updateFillColorSpace(GfxState * /*state*/) { }
202 virtual void updateStrokeColorSpace(GfxState * /*state*/) { }
203 virtual void updateFillColor(GfxState * /*state*/) { }
204 virtual void updateStrokeColor(GfxState * /*state*/) { }
205 virtual void updateBlendMode(GfxState * /*state*/) { }
206 virtual void updateFillOpacity(GfxState * /*state*/) { }
207 virtual void updateStrokeOpacity(GfxState * /*state*/) { }
208 virtual void updatePatternOpacity(GfxState * /*state*/) { }
209 virtual void clearPatternOpacity(GfxState * /*state*/) { }
210 virtual void updateFillOverprint(GfxState * /*state*/) { }
211 virtual void updateStrokeOverprint(GfxState * /*state*/) { }
212 virtual void updateOverprintMode(GfxState * /*state*/) { }
213 virtual void updateTransfer(GfxState * /*state*/) { }
214 virtual void updateFillColorStop(GfxState * /*state*/, double /*offset*/) { }
215
216 //----- update text state
217 virtual void updateFont(GfxState * /*state*/) { }
218 virtual void updateTextMat(GfxState * /*state*/) { }
219 virtual void updateCharSpace(GfxState * /*state*/) { }
220 virtual void updateRender(GfxState * /*state*/) { }
221 virtual void updateRise(GfxState * /*state*/) { }
222 virtual void updateWordSpace(GfxState * /*state*/) { }
223 virtual void updateHorizScaling(GfxState * /*state*/) { }
224 virtual void updateTextPos(GfxState * /*state*/) { }
225 virtual void updateTextShift(GfxState * /*state*/, double /*shift*/) { }
226 virtual void saveTextPos(GfxState * /*state*/) { }
227 virtual void restoreTextPos(GfxState * /*state*/) { }
228
229 //----- path painting
230 virtual void stroke(GfxState * /*state*/) { }
231 virtual void fill(GfxState * /*state*/) { }
232 virtual void eoFill(GfxState * /*state*/) { }
233 virtual bool tilingPatternFill(GfxState * /*state*/, Gfx * /*gfx*/, Catalog * /*cat*/, GfxTilingPattern * /*tPat*/, const double * /*mat*/, int /*x0*/, int /*y0*/, int /*x1*/, int /*y1*/, double /*xStep*/, double /*yStep*/)
234 {
235 return false;
236 }
237 virtual bool functionShadedFill(GfxState * /*state*/, GfxFunctionShading * /*shading*/) { return false; }
238 virtual bool axialShadedFill(GfxState * /*state*/, GfxAxialShading * /*shading*/, double /*tMin*/, double /*tMax*/) { return false; }
239 virtual bool axialShadedSupportExtend(GfxState * /*state*/, GfxAxialShading * /*shading*/) { return false; }
240 virtual bool radialShadedFill(GfxState * /*state*/, GfxRadialShading * /*shading*/, double /*sMin*/, double /*sMax*/) { return false; }
241 virtual bool radialShadedSupportExtend(GfxState * /*state*/, GfxRadialShading * /*shading*/) { return false; }
242 virtual bool gouraudTriangleShadedFill(GfxState *state, GfxGouraudTriangleShading *shading) { return false; }
243 virtual bool patchMeshShadedFill(GfxState *state, GfxPatchMeshShading *shading) { return false; }
244
245 //----- path clipping
246
247 // Update the clipping path. The new path is the intersection of the old path
248 // with the path given in 'state'.
249 // Additionally, set the clipping mode to the 'nonzero winding number rule'.
250 // That is, a point is inside the clipping region if its winding number
251 // with respect to the clipping path is nonzero.
252 virtual void clip(GfxState * /*state*/) { }
253
254 // Update the clipping path. The new path is the intersection of the old path
255 // with the path given in 'state'.
256 // Additionally, set the clipping mode to the 'even-odd rule'. That is, a point is
257 // inside the clipping region if a ray from it to infinity will cross the clipping
258 // path an odd number of times (disregarding the path orientation).
259 virtual void eoClip(GfxState * /*state*/) { }
260
261 // Update the clipping path. Unlike for the previous two methods, the clipping region
262 // is not the region surrounded by the path in 'state', but rather the path itself,
263 // rendered with the current pen settings.
264 virtual void clipToStrokePath(GfxState * /*state*/) { }
265
266 //----- text drawing
267 virtual void beginStringOp(GfxState * /*state*/) { }
268 virtual void endStringOp(GfxState * /*state*/) { }
269 virtual void beginString(GfxState * /*state*/, const GooString * /*s*/) { }
270 virtual void endString(GfxState * /*state*/) { }
271
272 // Draw one glyph at a specified position
273 //
274 // Arguments are:
275 // CharCode code: This is the character code in the content stream. It needs to be mapped back to a glyph index.
276 // int nBytes: The text strings in the content stream can consists of either 8-bit or 16-bit
277 // character codes depending on the font. nBytes is the number of bytes in the character code.
278 // Unicode *u: The UCS-4 mapping used for text extraction (TextOutputDev).
279 // int uLen: The number of unicode entries in u. Usually '1', for a single character,
280 // but it may also have larger values, for example for ligatures.
281 virtual void drawChar(GfxState * /*state*/, double /*x*/, double /*y*/, double /*dx*/, double /*dy*/, double /*originX*/, double /*originY*/, CharCode /*code*/, int /*nBytes*/, const Unicode * /*u*/, int /*uLen*/) { }
282 virtual void drawString(GfxState * /*state*/, const GooString * /*s*/) { }
283 virtual bool beginType3Char(GfxState * /*state*/, double /*x*/, double /*y*/, double /*dx*/, double /*dy*/, CharCode /*code*/, const Unicode * /*u*/, int /*uLen*/);
284 virtual void endType3Char(GfxState * /*state*/) { }
285 virtual void beginTextObject(GfxState * /*state*/) { }
286 virtual void endTextObject(GfxState * /*state*/) { }
287 virtual void incCharCount(int /*nChars*/) { }
288 virtual void beginActualText(GfxState * /*state*/, const GooString * /*text*/) { }
289 virtual void endActualText(GfxState * /*state*/) { }
290
291 //----- image drawing
292 // Draw an image mask. An image mask is a one-bit-per-pixel image, where each pixel
293 // can only be 'fill color' or 'transparent'.
294 //
295 // If 'invert' is false, a sample value of 0 marks the page with the current color,
296 // and a 1 leaves the previous contents unchanged. If 'invert' is true, these meanings are reversed.
297 virtual void drawImageMask(GfxState *state, Object *ref, Stream *str, int width, int height, bool invert, bool interpolate, bool inlineImg);
298 virtual void setSoftMaskFromImageMask(GfxState *state, Object *ref, Stream *str, int width, int height, bool invert, bool inlineImg, double *baseMatrix);
299 virtual void unsetSoftMaskFromImageMask(GfxState *state, double *baseMatrix);
300 virtual void drawImage(GfxState *state, Object *ref, Stream *str, int width, int height, GfxImageColorMap *colorMap, bool interpolate, const int *maskColors, bool inlineImg);
301 virtual void drawMaskedImage(GfxState *state, Object *ref, Stream *str, int width, int height, GfxImageColorMap *colorMap, bool interpolate, Stream *maskStr, int maskWidth, int maskHeight, bool maskInvert, bool maskInterpolate);
302 virtual void drawSoftMaskedImage(GfxState *state, Object *ref, Stream *str, int width, int height, GfxImageColorMap *colorMap, bool interpolate, Stream *maskStr, int maskWidth, int maskHeight, GfxImageColorMap *maskColorMap,
303 bool maskInterpolate);
304
305 //----- grouping operators
306
307 virtual void endMarkedContent(GfxState *state);
308 virtual void beginMarkedContent(const char *name, Dict *properties);
309 virtual void markPoint(const char *name);
310 virtual void markPoint(const char *name, Dict *properties);
311
312#ifdef OPI_SUPPORT
313 //----- OPI functions
314 virtual void opiBegin(GfxState *state, Dict *opiDict);
315 virtual void opiEnd(GfxState *state, Dict *opiDict);
316#endif
317
318 //----- Type 3 font operators
319 virtual void type3D0(GfxState * /*state*/, double /*wx*/, double /*wy*/) { }
320 virtual void type3D1(GfxState * /*state*/, double /*wx*/, double /*wy*/, double /*llx*/, double /*lly*/, double /*urx*/, double /*ury*/) { }
321
322 //----- form XObjects
323 virtual void beginForm(Object * /* obj */, Ref /*id*/) { }
324 virtual void drawForm(Ref /*id*/) { }
325 virtual void endForm(Object * /* obj */, Ref /*id*/) { }
326
327 //----- PostScript XObjects
328 virtual void psXObject(Stream * /*psStream*/, Stream * /*level1Stream*/) { }
329
330 //----- Profiling
331 void startProfile();
332 std::unordered_map<std::string, ProfileData> *getProfileHash() const { return profileHash.get(); }
333 std::unique_ptr<std::unordered_map<std::string, ProfileData>> endProfile();
334
335 //----- transparency groups and soft masks
336 virtual bool checkTransparencyGroup(GfxState * /*state*/, bool /*knockout*/) { return true; }
337 virtual void beginTransparencyGroup(GfxState * /*state*/, const double * /*bbox*/, GfxColorSpace * /*blendingColorSpace*/, bool /*isolated*/, bool /*knockout*/, bool /*forSoftMask*/) { }
338 virtual void endTransparencyGroup(GfxState * /*state*/) { }
339 virtual void paintTransparencyGroup(GfxState * /*state*/, const double * /*bbox*/) { }
340 virtual void setSoftMask(GfxState * /*state*/, const double * /*bbox*/, bool /*alpha*/, Function * /*transferFunc*/, GfxColor * /*backdropColor*/) { }
341 virtual void clearSoftMask(GfxState * /*state*/) { }
342
343 //----- links
344 virtual void processLink(AnnotLink * /*link*/) { }
345
346#if 1 //~tmp: turn off anti-aliasing temporarily
347 virtual bool getVectorAntialias() { return false; }
348 virtual void setVectorAntialias(bool /*vaa*/) { }
349#endif
350
351#ifdef USE_CMS
352 void setDisplayProfile(const GfxLCMSProfilePtr &profile) { displayprofile = profile; }
353 GfxLCMSProfilePtr getDisplayProfile() const { return displayprofile; }
354 void setDefaultGrayProfile(const GfxLCMSProfilePtr &profile) { defaultGrayProfile = profile; }
355 GfxLCMSProfilePtr getDefaultGrayProfile() const { return defaultGrayProfile; }
356 void setDefaultRGBProfile(const GfxLCMSProfilePtr &profile) { defaultRGBProfile = profile; }
357 GfxLCMSProfilePtr getDefaultRGBProfile() const { return defaultRGBProfile; }
358 void setDefaultCMYKProfile(const GfxLCMSProfilePtr &profile) { defaultCMYKProfile = profile; }
359 GfxLCMSProfilePtr getDefaultCMYKProfile() const { return defaultCMYKProfile; }
360
361 PopplerCache<Ref, GfxICCBasedColorSpace> *getIccColorSpaceCache() { return &iccColorSpaceCache; }
362#endif
363
364private:
365 double defCTM[6]; // default coordinate transform matrix
366 double defICTM[6]; // inverse of default CTM
367 std::unique_ptr<std::unordered_map<std::string, ProfileData>> profileHash;
368
369#ifdef USE_CMS
370 GfxLCMSProfilePtr displayprofile;
371 GfxLCMSProfilePtr defaultGrayProfile;
372 GfxLCMSProfilePtr defaultRGBProfile;
373 GfxLCMSProfilePtr defaultCMYKProfile;
374
375 PopplerCache<Ref, GfxICCBasedColorSpace> iccColorSpaceCache;
376#endif
377};
378
379#endif
380

source code of poppler/poppler/OutputDev.h