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 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 50 class Annot; 51 class Dict; 52 class GooString; 53 class Gfx; 54 class Stream; 55 class Links; 56 class AnnotLink; 57 class Catalog; 58 class Page; 59 class Function; 60 61 //------------------------------------------------------------------------ 62 // OutputDev 63 //------------------------------------------------------------------------ 64 65 class POPPLER_PRIVATE_EXPORT OutputDev 66 { 67 public: 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. useTilingPatternFill()86 virtual bool useTilingPatternFill() { return false; } 87 88 // Does this device support specific shading types? 89 // see gouraudTriangleShadedFill() and patchMeshShadedFill() useShadedFills(int type)90 virtual bool useShadedFills(int type) { return false; } 91 92 // Does this device use FillColorStop()? useFillColorStop()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). useDrawForm()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? needNonText()104 virtual bool needNonText() { return true; } 105 106 // Does this device require incCharCount to be called for text on 107 // non-shown layers? needCharCount()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? needClipToCropBox()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. startPage(int pageNum,GfxState * state,XRef * xref)130 virtual void startPage(int pageNum, GfxState *state, XRef *xref) { } 131 132 // End a page. endPage()133 virtual void endPage() { } 134 135 // Dump page contents to display. dump()136 virtual void dump() { } 137 initGfxState(GfxState * state)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 getDefCTM()176 const double *getDefCTM() const { return defCTM; } getDefICTM()177 const double *getDefICTM() const { return defICTM; } 178 179 //----- save/restore graphics state saveState(GfxState *)180 virtual void saveState(GfxState * /*state*/) { } restoreState(GfxState *)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. updateCTM(GfxState *,double,double,double,double,double,double)191 virtual void updateCTM(GfxState * /*state*/, double /*m11*/, double /*m12*/, double /*m21*/, double /*m22*/, double /*m31*/, double /*m32*/) { } updateLineDash(GfxState *)192 virtual void updateLineDash(GfxState * /*state*/) { } updateFlatness(GfxState *)193 virtual void updateFlatness(GfxState * /*state*/) { } updateLineJoin(GfxState *)194 virtual void updateLineJoin(GfxState * /*state*/) { } updateLineCap(GfxState *)195 virtual void updateLineCap(GfxState * /*state*/) { } updateMiterLimit(GfxState *)196 virtual void updateMiterLimit(GfxState * /*state*/) { } updateLineWidth(GfxState *)197 virtual void updateLineWidth(GfxState * /*state*/) { } updateStrokeAdjust(GfxState *)198 virtual void updateStrokeAdjust(GfxState * /*state*/) { } updateAlphaIsShape(GfxState *)199 virtual void updateAlphaIsShape(GfxState * /*state*/) { } updateTextKnockout(GfxState *)200 virtual void updateTextKnockout(GfxState * /*state*/) { } updateFillColorSpace(GfxState *)201 virtual void updateFillColorSpace(GfxState * /*state*/) { } updateStrokeColorSpace(GfxState *)202 virtual void updateStrokeColorSpace(GfxState * /*state*/) { } updateFillColor(GfxState *)203 virtual void updateFillColor(GfxState * /*state*/) { } updateStrokeColor(GfxState *)204 virtual void updateStrokeColor(GfxState * /*state*/) { } updateBlendMode(GfxState *)205 virtual void updateBlendMode(GfxState * /*state*/) { } updateFillOpacity(GfxState *)206 virtual void updateFillOpacity(GfxState * /*state*/) { } updateStrokeOpacity(GfxState *)207 virtual void updateStrokeOpacity(GfxState * /*state*/) { } updatePatternOpacity(GfxState *)208 virtual void updatePatternOpacity(GfxState * /*state*/) { } clearPatternOpacity(GfxState *)209 virtual void clearPatternOpacity(GfxState * /*state*/) { } updateFillOverprint(GfxState *)210 virtual void updateFillOverprint(GfxState * /*state*/) { } updateStrokeOverprint(GfxState *)211 virtual void updateStrokeOverprint(GfxState * /*state*/) { } updateOverprintMode(GfxState *)212 virtual void updateOverprintMode(GfxState * /*state*/) { } updateTransfer(GfxState *)213 virtual void updateTransfer(GfxState * /*state*/) { } updateFillColorStop(GfxState *,double)214 virtual void updateFillColorStop(GfxState * /*state*/, double /*offset*/) { } 215 216 //----- update text state updateFont(GfxState *)217 virtual void updateFont(GfxState * /*state*/) { } updateTextMat(GfxState *)218 virtual void updateTextMat(GfxState * /*state*/) { } updateCharSpace(GfxState *)219 virtual void updateCharSpace(GfxState * /*state*/) { } updateRender(GfxState *)220 virtual void updateRender(GfxState * /*state*/) { } updateRise(GfxState *)221 virtual void updateRise(GfxState * /*state*/) { } updateWordSpace(GfxState *)222 virtual void updateWordSpace(GfxState * /*state*/) { } updateHorizScaling(GfxState *)223 virtual void updateHorizScaling(GfxState * /*state*/) { } updateTextPos(GfxState *)224 virtual void updateTextPos(GfxState * /*state*/) { } updateTextShift(GfxState *,double)225 virtual void updateTextShift(GfxState * /*state*/, double /*shift*/) { } saveTextPos(GfxState *)226 virtual void saveTextPos(GfxState * /*state*/) { } restoreTextPos(GfxState *)227 virtual void restoreTextPos(GfxState * /*state*/) { } 228 229 //----- path painting stroke(GfxState *)230 virtual void stroke(GfxState * /*state*/) { } fill(GfxState *)231 virtual void fill(GfxState * /*state*/) { } eoFill(GfxState *)232 virtual void eoFill(GfxState * /*state*/) { } tilingPatternFill(GfxState *,Gfx *,Catalog *,GfxTilingPattern *,const double *,int,int,int,int,double,double)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 } functionShadedFill(GfxState *,GfxFunctionShading *)237 virtual bool functionShadedFill(GfxState * /*state*/, GfxFunctionShading * /*shading*/) { return false; } axialShadedFill(GfxState *,GfxAxialShading *,double,double)238 virtual bool axialShadedFill(GfxState * /*state*/, GfxAxialShading * /*shading*/, double /*tMin*/, double /*tMax*/) { return false; } axialShadedSupportExtend(GfxState *,GfxAxialShading *)239 virtual bool axialShadedSupportExtend(GfxState * /*state*/, GfxAxialShading * /*shading*/) { return false; } radialShadedFill(GfxState *,GfxRadialShading *,double,double)240 virtual bool radialShadedFill(GfxState * /*state*/, GfxRadialShading * /*shading*/, double /*sMin*/, double /*sMax*/) { return false; } radialShadedSupportExtend(GfxState *,GfxRadialShading *)241 virtual bool radialShadedSupportExtend(GfxState * /*state*/, GfxRadialShading * /*shading*/) { return false; } gouraudTriangleShadedFill(GfxState * state,GfxGouraudTriangleShading * shading)242 virtual bool gouraudTriangleShadedFill(GfxState *state, GfxGouraudTriangleShading *shading) { return false; } patchMeshShadedFill(GfxState * state,GfxPatchMeshShading * shading)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. clip(GfxState *)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). eoClip(GfxState *)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. clipToStrokePath(GfxState *)264 virtual void clipToStrokePath(GfxState * /*state*/) { } 265 266 //----- text drawing beginStringOp(GfxState *)267 virtual void beginStringOp(GfxState * /*state*/) { } endStringOp(GfxState *)268 virtual void endStringOp(GfxState * /*state*/) { } beginString(GfxState *,const GooString *)269 virtual void beginString(GfxState * /*state*/, const GooString * /*s*/) { } endString(GfxState *)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. drawChar(GfxState *,double,double,double,double,double,double,CharCode,int,const Unicode *,int)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*/) { } drawString(GfxState *,const GooString *)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*/); endType3Char(GfxState *)284 virtual void endType3Char(GfxState * /*state*/) { } beginTextObject(GfxState *)285 virtual void beginTextObject(GfxState * /*state*/) { } endTextObject(GfxState *)286 virtual void endTextObject(GfxState * /*state*/) { } incCharCount(int)287 virtual void incCharCount(int /*nChars*/) { } beginActualText(GfxState *,const GooString *)288 virtual void beginActualText(GfxState * /*state*/, const GooString * /*text*/) { } endActualText(GfxState *)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 type3D0(GfxState *,double,double)319 virtual void type3D0(GfxState * /*state*/, double /*wx*/, double /*wy*/) { } type3D1(GfxState *,double,double,double,double,double,double)320 virtual void type3D1(GfxState * /*state*/, double /*wx*/, double /*wy*/, double /*llx*/, double /*lly*/, double /*urx*/, double /*ury*/) { } 321 322 //----- form XObjects beginForm(Ref)323 virtual void beginForm(Ref /*id*/) { } drawForm(Ref)324 virtual void drawForm(Ref /*id*/) { } endForm(Ref)325 virtual void endForm(Ref /*id*/) { } 326 327 //----- PostScript XObjects psXObject(Stream *,Stream *)328 virtual void psXObject(Stream * /*psStream*/, Stream * /*level1Stream*/) { } 329 330 //----- Profiling 331 void startProfile(); getProfileHash()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 checkTransparencyGroup(GfxState *,bool)336 virtual bool checkTransparencyGroup(GfxState * /*state*/, bool /*knockout*/) { return true; } beginTransparencyGroup(GfxState *,const double *,GfxColorSpace *,bool,bool,bool)337 virtual void beginTransparencyGroup(GfxState * /*state*/, const double * /*bbox*/, GfxColorSpace * /*blendingColorSpace*/, bool /*isolated*/, bool /*knockout*/, bool /*forSoftMask*/) { } endTransparencyGroup(GfxState *)338 virtual void endTransparencyGroup(GfxState * /*state*/) { } paintTransparencyGroup(GfxState *,const double *)339 virtual void paintTransparencyGroup(GfxState * /*state*/, const double * /*bbox*/) { } setSoftMask(GfxState *,const double *,bool,Function *,GfxColor *)340 virtual void setSoftMask(GfxState * /*state*/, const double * /*bbox*/, bool /*alpha*/, Function * /*transferFunc*/, GfxColor * /*backdropColor*/) { } clearSoftMask(GfxState *)341 virtual void clearSoftMask(GfxState * /*state*/) { } 342 343 //----- links processLink(AnnotLink *)344 virtual void processLink(AnnotLink * /*link*/) { } 345 346 #if 1 //~tmp: turn off anti-aliasing temporarily getVectorAntialias()347 virtual bool getVectorAntialias() { return false; } setVectorAntialias(bool)348 virtual void setVectorAntialias(bool /*vaa*/) { } 349 #endif 350 351 #ifdef USE_CMS setDisplayProfile(const GfxLCMSProfilePtr & profile)352 void setDisplayProfile(const GfxLCMSProfilePtr &profile) { displayprofile = profile; } getDisplayProfile()353 GfxLCMSProfilePtr getDisplayProfile() const { return displayprofile; } setDefaultGrayProfile(const GfxLCMSProfilePtr & profile)354 void setDefaultGrayProfile(const GfxLCMSProfilePtr &profile) { defaultGrayProfile = profile; } getDefaultGrayProfile()355 GfxLCMSProfilePtr getDefaultGrayProfile() const { return defaultGrayProfile; } setDefaultRGBProfile(const GfxLCMSProfilePtr & profile)356 void setDefaultRGBProfile(const GfxLCMSProfilePtr &profile) { defaultRGBProfile = profile; } getDefaultRGBProfile()357 GfxLCMSProfilePtr getDefaultRGBProfile() const { return defaultRGBProfile; } setDefaultCMYKProfile(const GfxLCMSProfilePtr & profile)358 void setDefaultCMYKProfile(const GfxLCMSProfilePtr &profile) { defaultCMYKProfile = profile; } getDefaultCMYKProfile()359 GfxLCMSProfilePtr getDefaultCMYKProfile() const { return defaultCMYKProfile; } 360 getIccColorSpaceCache()361 PopplerCache<Ref, GfxICCBasedColorSpace> *getIccColorSpaceCache() { return &iccColorSpaceCache; } 362 #endif 363 364 private: 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