1 /* 2 For general Scribus (>=1.3.2) copyright and licensing information please refer 3 to the COPYING file provided with the program. Following this notice may exist 4 a copyright and/or license notice that predates the release of Scribus 1.3.2 5 for which a new license (GPL+exception) is in place. 6 */ 7 #ifndef SLAOUTPUT_H 8 #define SLAOUTPUT_H 9 10 #include <QBuffer> 11 #include <QColor> 12 #include <QBrush> 13 #include <QDebug> 14 #include <QImage> 15 #include <QPen> 16 #include <QList> 17 #include <QSizeF> 18 #include <QStack> 19 #include <QString> 20 #include <QTextStream> 21 #include <QTransform> 22 23 #include <memory> 24 25 #include "fpointarray.h" 26 #include "importpdfconfig.h" 27 #include "pageitem.h" 28 #include "scribusdoc.h" 29 #include "scribusview.h" 30 #include "selection.h" 31 #include "vgradient.h" 32 33 #if POPPLER_ENCODED_VERSION < POPPLER_VERSION_ENCODE(0, 73, 0) 34 #include <poppler/goo/gtypes.h> 35 #endif 36 #include <poppler/Object.h> 37 #include <poppler/OutputDev.h> 38 #include <poppler/Gfx.h> 39 #include <poppler/GfxState.h> 40 #include <poppler/Stream.h> 41 #include <poppler/GfxFont.h> 42 #include <poppler/Link.h> 43 #include <poppler/PDFDoc.h> 44 #include <poppler/Error.h> 45 #include <poppler/Form.h> 46 #include <poppler/Page.h> 47 #include <poppler/Catalog.h> 48 #include <poppler/CharCodeToUnicode.h> 49 #include <poppler/FontEncodingTables.h> 50 #include <poppler/splash/SplashFontFileID.h> 51 #include <poppler/splash/SplashFontFile.h> 52 #include <poppler/splash/SplashFontEngine.h> 53 #include <poppler/splash/SplashFont.h> 54 #include <poppler/splash/SplashMath.h> 55 #include <poppler/splash/SplashPath.h> 56 #include <poppler/splash/SplashGlyphBitmap.h> 57 58 //------------------------------------------------------------------------ 59 // LinkSubmitData 60 //------------------------------------------------------------------------ 61 62 class LinkSubmitForm: public LinkAction 63 { 64 public: 65 // Build a LinkImportData from an action dictionary. 66 LinkSubmitForm(Object *actionObj); 67 // Destructor. 68 virtual ~LinkSubmitForm(); 69 70 // Was the LinkImportData created successfully? isOk()71 GBool isOk() POPPLER_CONST override { return fileName != nullptr; } 72 // Accessors. getKind()73 LinkActionKind getKind() POPPLER_CONST override { return actionUnknown; } getFileName()74 GooString *getFileName() { return fileName; } getFlags()75 int getFlags() { return m_flags; } 76 77 private: 78 GooString *fileName {nullptr}; // file name 79 int m_flags {0}; 80 }; 81 82 //------------------------------------------------------------------------ 83 // LinkImportData 84 //------------------------------------------------------------------------ 85 86 class LinkImportData: public LinkAction 87 { 88 public: 89 // Build a LinkImportData from an action dictionary. 90 LinkImportData(Object *actionObj); 91 // Destructor. 92 virtual ~LinkImportData(); 93 94 // Was the LinkImportData created successfully? isOk()95 GBool isOk() POPPLER_CONST override { return fileName != nullptr; } 96 // Accessors. getKind()97 LinkActionKind getKind() POPPLER_CONST override { return actionUnknown; } getFileName()98 GooString *getFileName() { return fileName; } 99 100 private: 101 GooString *fileName {nullptr}; // file name 102 }; 103 104 //------------------------------------------------------------------------ 105 // SlaOutFontFileID 106 //------------------------------------------------------------------------ 107 108 class SlaOutFontFileID: public SplashFontFileID 109 { 110 public: SlaOutFontFileID(const Ref * rA)111 SlaOutFontFileID(const Ref *rA) { r = *rA; } ~SlaOutFontFileID()112 ~SlaOutFontFileID() {} 113 matches(SplashFontFileID * id)114 GBool matches(SplashFontFileID *id) override 115 { 116 return ((SlaOutFontFileID*) id)->r.num == r.num && ((SlaOutFontFileID *) id)->r.gen == r.gen; 117 } 118 119 private: 120 Ref r; 121 }; 122 123 124 class AnoOutputDev : public OutputDev 125 { 126 public: 127 AnoOutputDev(ScribusDoc* doc, QStringList *importedColors); 128 virtual ~AnoOutputDev(); 129 isOk()130 GBool isOk() { return gTrue; } upsideDown()131 GBool upsideDown() override { return gTrue; } useDrawChar()132 GBool useDrawChar() override { return gFalse; } interpretType3Chars()133 GBool interpretType3Chars() override { return gFalse; } useTilingPatternFill()134 GBool useTilingPatternFill() override { return gFalse; } useShadedFills(int type)135 GBool useShadedFills(int type) override { return gFalse; } useFillColorStop()136 GBool useFillColorStop() override { return gFalse; } useDrawForm()137 GBool useDrawForm() override { return gFalse; } 138 139 void stroke(GfxState *state) override; 140 void eoFill(GfxState *state) override; 141 void fill(GfxState *state) override; 142 void drawString(GfxState *state, POPPLER_CONST GooString *s) override; 143 144 QString currColorText; 145 QString currColorFill; 146 QString currColorStroke; 147 double fontSize {12}; 148 GooString *fontName {nullptr}; 149 GooString *itemText {nullptr}; 150 151 private: 152 QString getColor(GfxColorSpace *color_space, POPPLER_CONST_070 GfxColor *color, int *shade); 153 ScribusDoc* m_doc; 154 QStringList *m_importedColors; 155 }; 156 157 158 159 class SlaOutputDev : public OutputDev 160 { 161 public: 162 SlaOutputDev(ScribusDoc* doc, QList<PageItem*> *Elements, QStringList *importedColors, int flags); 163 virtual ~SlaOutputDev(); 164 165 LinkAction* SC_getAction(AnnotWidget *ano); 166 #if POPPLER_ENCODED_VERSION >= POPPLER_VERSION_ENCODE(0, 86, 0) 167 std::unique_ptr<LinkAction> SC_getAdditionalAction(const char *key, AnnotWidget *ano); 168 #else 169 LinkAction* SC_getAdditionalAction(const char *key, AnnotWidget *ano); 170 #endif 171 static GBool annotations_callback(Annot *annota, void *user_data); 172 bool handleTextAnnot(Annot* annota, double xCoor, double yCoor, double width, double height); 173 bool handleLinkAnnot(Annot* annota, double xCoor, double yCoor, double width, double height); 174 bool handleWidgetAnnot(Annot* annota, double xCoor, double yCoor, double width, double height); 175 void applyTextStyle(PageItem* ite, const QString& fontName, const QString& textColor, double fontSize); 176 void handleActions(PageItem* ite, AnnotWidget *ano); 177 void startDoc(PDFDoc *doc, XRef *xrefA, Catalog *catA); 178 isOk()179 GBool isOk() { return gTrue; } upsideDown()180 GBool upsideDown() override { return gTrue; } useDrawChar()181 GBool useDrawChar() override { return gTrue; } interpretType3Chars()182 GBool interpretType3Chars() override { return gTrue; } useTilingPatternFill()183 GBool useTilingPatternFill() override { return gTrue; } useShadedFills(int type)184 GBool useShadedFills(int type) override { return type <= 7; } useFillColorStop()185 GBool useFillColorStop() override { return gTrue; } useDrawForm()186 GBool useDrawForm() override { return gFalse; } 187 188 // virtual GBool needClipToCropBox() { return gTrue; } 189 void startPage(int pageNum, GfxState *, XRef *) override; 190 void endPage() override; 191 192 // graphics state 193 void saveState(GfxState *state) override; 194 void restoreState(GfxState *state) override; 195 196 //----- path painting 197 void stroke(GfxState *state) override; 198 void fill(GfxState *state) override; 199 void eoFill(GfxState *state) override; 200 #if POPPLER_ENCODED_VERSION >= POPPLER_VERSION_ENCODE(21, 3, 0) 201 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) override; 202 #else 203 GBool tilingPatternFill(GfxState *state, Gfx *gfx, Catalog *cat, Object *str, POPPLER_CONST_070 double *pmat, int paintType, int tilingType, Dict *resDict, POPPLER_CONST_070 double *mat, POPPLER_CONST_070 double *bbox, int x0, int y0, int x1, int y1, double xStep, double yStep) override; 204 #endif functionShadedFill(GfxState *,GfxFunctionShading *)205 GBool functionShadedFill(GfxState * /*state*/, GfxFunctionShading * /*shading*/) override { qDebug() << "Function Shaded Fill"; return gFalse; } 206 GBool axialShadedFill(GfxState *state, GfxAxialShading *shading, double tMin, double tMax) override; axialShadedSupportExtend(GfxState * state,GfxAxialShading * shading)207 GBool axialShadedSupportExtend(GfxState *state, GfxAxialShading *shading) override { return (shading->getExtend0() == shading->getExtend1()); } 208 GBool radialShadedFill(GfxState *state, GfxRadialShading *shading, double sMin, double sMax) override; radialShadedSupportExtend(GfxState * state,GfxRadialShading * shading)209 GBool radialShadedSupportExtend(GfxState *state, GfxRadialShading *shading) override { return (shading->getExtend0() == shading->getExtend1()); } 210 GBool gouraudTriangleShadedFill(GfxState *state, GfxGouraudTriangleShading *shading) override; 211 GBool patchMeshShadedFill(GfxState *state, GfxPatchMeshShading *shading) override; 212 213 //----- path clipping 214 void clip(GfxState *state) override; 215 void eoClip(GfxState *state) override; clipToStrokePath(GfxState *)216 void clipToStrokePath(GfxState * /*state*/) override { qDebug() << "Clip to StrokePath"; } deviceHasTextClip(GfxState * state)217 virtual GBool deviceHasTextClip(GfxState *state) { return gFalse; } 218 219 // If current colorspace is pattern, 220 // does this device support text in pattern colorspace? supportTextCSPattern(GfxState * state)221 virtual GBool supportTextCSPattern(GfxState *state) 222 { 223 return state->getFillColorSpace()->getMode() == csPattern; 224 } 225 226 // If current colorspace is pattern, 227 // need this device special handling for masks in pattern colorspace? fillMaskCSPattern(GfxState * state)228 virtual GBool fillMaskCSPattern(GfxState * state) 229 { 230 return state->getFillColorSpace()->getMode() == csPattern; 231 } 232 endMaskClip(GfxState * state)233 virtual void endMaskClip(GfxState *state) { qDebug() << "End Mask Clip"; } 234 235 //----- grouping operators 236 void beginMarkedContent(POPPLER_CONST char *name, Dict *properties) override; 237 virtual void beginMarkedContent(POPPLER_CONST char *name, Object *dictRef); 238 void endMarkedContent(GfxState *state) override; 239 void markPoint(POPPLER_CONST char *name) override; 240 void markPoint(POPPLER_CONST char *name, Dict *properties) override; 241 242 //----- image drawing 243 void drawImageMask(GfxState *state, Object *ref, Stream *str, int width, int height, GBool invert, GBool interpolate, GBool inlineImg) override; 244 void drawImage(GfxState *state, Object *ref, Stream *str, int width, int height, GfxImageColorMap *colorMap, GBool interpolate, POPPLER_CONST_082 int *maskColors, GBool inlineImg) override; 245 void drawSoftMaskedImage(GfxState *state, Object *ref, Stream *str, 246 int width, int height, 247 GfxImageColorMap *colorMap, 248 GBool interpolate, 249 Stream *maskStr, 250 int maskWidth, int maskHeight, 251 GfxImageColorMap *maskColorMap, 252 GBool maskInterpolate) override; 253 254 void drawMaskedImage(GfxState *state, Object *ref, Stream *str, 255 int width, int height, 256 GfxImageColorMap *colorMap, 257 GBool interpolate, 258 Stream *maskStr, 259 int maskWidth, int maskHeight, 260 GBool maskInvert, GBool maskInterpolate) override; // { qDebug() << "Draw Masked Image"; } 261 262 //----- transparency groups and soft masks 263 void beginTransparencyGroup(GfxState *state, POPPLER_CONST_070 double *bbox, GfxColorSpace * /*blendingColorSpace*/, GBool /*isolated*/, GBool /*knockout*/, GBool /*forSoftMask*/) override; 264 void paintTransparencyGroup(GfxState *state, POPPLER_CONST_070 double *bbox) override; 265 void endTransparencyGroup(GfxState *state) override; 266 void setSoftMask(GfxState * /*state*/, POPPLER_CONST_070 double * /*bbox*/, GBool /*alpha*/, Function * /*transferFunc*/, GfxColor * /*backdropColor*/) override; 267 void clearSoftMask(GfxState * /*state*/) override; 268 269 void updateFillColor(GfxState *state) override; 270 void updateStrokeColor(GfxState *state) override; 271 void updateFont(GfxState* state) override; 272 273 //----- text drawing 274 void beginTextObject(GfxState *state) override; 275 void endTextObject(GfxState *state) override; 276 void drawChar(GfxState *state, double /*x*/, double /*y*/, double /*dx*/, double /*dy*/, double /*originX*/, double /*originY*/, CharCode /*code*/, int /*nBytes*/, POPPLER_CONST_082 Unicode * /*u*/, int /*uLen*/) override; 277 GBool beginType3Char(GfxState * /*state*/, double /*x*/, double /*y*/, double /*dx*/, double /*dy*/, CharCode /*code*/, POPPLER_CONST_082 Unicode * /*u*/, int /*uLen*/) override; 278 void endType3Char(GfxState * /*state*/) override; 279 void type3D0(GfxState * /*state*/, double /*wx*/, double /*wy*/) override; 280 void type3D1(GfxState * /*state*/, double /*wx*/, double /*wy*/, double /*llx*/, double /*lly*/, double /*urx*/, double /*ury*/) override; 281 282 //----- form XObjects drawForm(Ref)283 void drawForm(Ref /*id*/) override { qDebug() << "Draw Form"; } 284 285 //----- links processLink(AnnotLink *)286 void processLink(AnnotLink * /*link*/) override { qDebug() << "Draw Link"; } 287 288 bool layersSetByOCG { false }; 289 double cropOffsetX { 0.0 }; 290 double cropOffsetY { 0.0 }; 291 int rotate { 0 }; 292 293 protected: 294 void setItemFillAndStroke(GfxState* state, PageItem* textNode); 295 void applyMask(PageItem* ite); 296 void pushGroup(const QString& maskName = "", GBool forSoftMask = gFalse, GBool alpha = gFalse, bool inverted = false); 297 298 ScribusDoc* m_doc; 299 Qt::PenCapStyle m_lineEnd { Qt::FlatCap }; 300 Qt::PenJoinStyle m_lineJoin { Qt::MiterJoin }; 301 QList<PageItem*>* m_Elements; 302 303 struct groupEntry 304 { 305 QList<PageItem*> Items; 306 GBool forSoftMask { gFalse }; 307 GBool isolated { gFalse }; 308 GBool alpha { gFalse }; 309 QString maskName; 310 QPointF maskPos; 311 bool inverted { false }; 312 }; 313 314 QStack<groupEntry> m_groupStack; 315 QString m_currColorFill; 316 QString m_currColorStroke; 317 int m_currFillShade { 100 }; 318 int m_currStrokeShade { 100 }; 319 320 private: 321 void getPenState(GfxState *state); 322 QString getColor(GfxColorSpace *color_space, POPPLER_CONST_070 GfxColor *color, int *shade); 323 QString getAnnotationColor(const AnnotColor *color); 324 QString convertPath(POPPLER_CONST_083 GfxPath *path); 325 int getBlendMode(GfxState *state); 326 QString UnicodeParsedString(POPPLER_CONST GooString *s1); 327 QString UnicodeParsedString(const std::string& s1); 328 bool checkClip(); 329 330 // Intersect the current clip path with the new path in state where filled areas 331 // are interpreted according to fillRule. 332 void adjustClip(GfxState *state, Qt::FillRule fillRule); 333 334 // Take the current path of state and interpret it according to fillRule, 335 // intersect it with the clipping path and create a new pageitem for it. 336 void createFillItem(GfxState *state, Qt::FillRule fillRule); 337 338 void createImageFrame(QImage& image, GfxState *state, int numColorComponents); 339 340 bool pathIsClosed { false }; 341 QVector<double> DashValues; 342 double DashOffset { 0.0 }; 343 QString Coords; 344 // The currently visible area. If it is empty, everything is visible. 345 // QPainterPath has the drawback that it sometimes approximates Bezier curves 346 // by line segments for numerical stability. If available, a better class 347 // should be used. However, it is important that the used class knows which 348 // areas are covered and does not rely on external information about the fill 349 // rule to use. 350 QPainterPath m_currentClipPath; 351 QStack<QPainterPath> m_clipPaths; 352 // Collect the paths of character glyphs for clipping of a whole text group. 353 QPainterPath m_clipTextPath; 354 355 QString m_currentMask; 356 QPointF m_currentMaskPosition; 357 Selection* tmpSel { nullptr }; 358 QStringList *m_importedColors; 359 QTransform m_ctm; 360 struct F3Entry 361 { 362 bool colored; 363 }; 364 QStack<F3Entry> m_F3Stack; 365 struct mContent 366 { 367 QString name; 368 QString ocgName; 369 }; 370 QStack<mContent> m_mcStack; 371 int inPattern {0}; 372 int layerNum {1}; 373 int currentLayer { 0 }; 374 bool firstLayer {true}; 375 int importerFlags; 376 int updateGUICounter {0}; 377 XRef *xref {nullptr}; // xref table for current document 378 PDFDoc *pdfDoc {nullptr}; 379 Catalog *catalog {nullptr}; 380 SplashFontEngine *m_fontEngine {nullptr}; 381 SplashFont *m_font {nullptr}; 382 #if POPPLER_ENCODED_VERSION >= POPPLER_VERSION_ENCODE(21, 4, 0) 383 std::unique_ptr<FormPageWidgets> m_formWidgets; 384 #else 385 FormPageWidgets *m_formWidgets {nullptr}; 386 #endif 387 QHash<QString, QList<int> > m_radioMap; 388 QHash<int, PageItem*> m_radioButtons; 389 int m_actPage { 1 }; 390 }; 391 #endif 392