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