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 #include "scpageoutput.h"
8 
9 #include <QList>
10 #include <QPointF>
11 #include <QRectF>
12 #include <QStack>
13 #include <pageitem_textframe.h>
14 #include "cmsettings.h"
15 #include "collapsedtablepainterex.h"
16 #include "commonstrings.h"
17 #include "pageitem.h"
18 #include "pageitem_arc.h"
19 #include "pageitem_group.h"
20 #include "pageitem_imageframe.h"
21 #include "pageitem_line.h"
22 #include "pageitem_polygon.h"
23 #include "pageitem_polyline.h"
24 #include "pageitem_regularpolygon.h"
25 #include "pageitem_spiral.h"
26 #include "pageitem_table.h"
27 #include "prefsmanager.h"
28 #include "scfonts.h"
29 #include "scimage.h"
30 #include "scpage.h"
31 #include "scpattern.h"
32 #include "text/textlayoutpainter.h"
33 
34 #include "scribusdoc.h"
35 #include "util.h"
36 #include "util_formats.h"
37 #include "util_math.h"
38 #include "text/boxes.h"
39 
40 
MarksOptions()41 MarksOptions::MarksOptions()
42 {
43 	markLength = 20.0;
44 	markOffset = 0.0;
45 	BleedTop = 0.0;
46 	BleedLeft = 0.0;
47 	BleedRight = 0.0;
48 	BleedBottom = 0.0;
49 	cropMarks = false;
50 	bleedMarks = false;
51 	registrationMarks = false;
52 	colorMarks = false;
53 	docInfoMarks = false;
54 }
55 
MarksOptions(struct PrintOptions & opt)56 MarksOptions::MarksOptions(struct PrintOptions& opt)
57 {
58 	markLength = opt.markLength;
59 	markOffset = opt.markOffset;
60 	BleedTop = opt.bleeds.top();
61 	BleedLeft = opt.bleeds.left();
62 	BleedRight = opt.bleeds.right();
63 	BleedBottom = opt.bleeds.bottom();
64 	cropMarks = opt.cropMarks;
65 	bleedMarks = opt.bleedMarks;
66 	registrationMarks = opt.registrationMarks;
67 	colorMarks = opt.colorMarks;
68 	docInfoMarks = true;
69 }
70 
ScPageOutput(ScribusDoc * doc,bool reloadImages,int resolution,bool useProfiles)71 ScPageOutput::ScPageOutput(ScribusDoc* doc, bool reloadImages, int resolution, bool useProfiles)
72 			: m_marksOptions()
73 {
74 	m_doc = doc;
75 	m_reloadImages = reloadImages;
76 	m_imageRes = resolution;
77 	m_useProfiles = useProfiles;
78 }
79 
translateImageModeToRequest(ScPainterExBase::ImageMode mode)80 ScImage::RequestType ScPageOutput::translateImageModeToRequest(ScPainterExBase::ImageMode mode)
81 {
82 	ScImage::RequestType value = ScImage::RGBData;
83 	if (mode == ScPainterExBase::cmykImages)
84 		value = ScImage::CMYKData;
85 	else if (mode == ScPainterExBase::rgbImages)
86 		value = ScImage::RGBData;
87 	else if (mode == ScPainterExBase::rawImages)
88 		value = ScImage::RawData;
89 	return value;
90 }
91 
drawPage(ScPage * page,ScPainterExBase * painter)92 void ScPageOutput::drawPage(ScPage* page, ScPainterExBase* painter)
93 {
94 	int clipx = static_cast<int>(page->xOffset());
95 	int clipy = static_cast<int>(page->yOffset());
96 	int clipw = qRound(page->width());
97 	int cliph = qRound(page->height());
98 	ScLayer layer;
99 	layer.isViewable = false;
100 	uint layerCount = m_doc->layerCount();
101 	for (uint la = 0; la < layerCount; ++la)
102 	{
103 		m_doc->Layers.levelToLayer(layer, la);
104 		drawMasterItems(painter, page, layer, QRect(clipx, clipy, clipw, cliph));
105 		drawPageItems(painter, page, layer, QRect(clipx, clipy, clipw, cliph));
106 	}
107 	drawMarks(page, painter, m_marksOptions);
108 }
109 
drawMasterItems(ScPainterExBase * painter,ScPage * page,ScLayer & layer,QRect clip)110 void ScPageOutput::drawMasterItems(ScPainterExBase *painter, ScPage *page, ScLayer& layer, QRect clip)
111 {
112 	PageItem* currItem;
113 	if (page->masterPageNameEmpty())
114 		return;
115 	if (page->FromMaster.count() <= 0)
116 		return;
117 	if (!layer.isViewable || !layer.isPrintable)
118 		return;
119 	ScPage* Mp = m_doc->MasterPages.at(m_doc->MasterNames[page->masterPageName()]);
120 	int pageFromMasterCount = page->FromMaster.count();
121 	for (int i = 0; i < pageFromMasterCount; ++i)
122 	{
123 		currItem = page->FromMaster.at(i);
124 		if (currItem->m_layerID != layer.ID)
125 			continue;
126 		if ((currItem->OwnPage != -1) && (currItem->OwnPage != static_cast<int>(Mp->pageNr())))
127 			continue;
128 		if (!currItem->printEnabled())
129 			continue;
130 		int savedOwnPage = currItem->OwnPage;
131 		double OldX = currItem->xPos();
132 		double OldY = currItem->yPos();
133 		double OldBX = currItem->BoundingX;
134 		double OldBY = currItem->BoundingY;
135 		currItem->OwnPage = page->pageNr();
136 		if (!currItem->ChangedMasterItem)
137 		{
138 			currItem->moveBy(-Mp->xOffset() + page->xOffset(), -Mp->yOffset() + page->yOffset(), true);
139 			currItem->BoundingX = OldBX - Mp->xOffset() + page->xOffset();
140 			currItem->BoundingY = OldBY - Mp->yOffset() + page->yOffset();
141 		}
142 		QRectF oldR(currItem->getBoundingRect().adjusted(0.0, 0.0, 1.0, 1.0));
143 		if (clip.intersects(oldR.toRect()))
144 			drawItem(currItem, painter, clip);
145 		currItem->OwnPage = savedOwnPage;
146 		if (!currItem->ChangedMasterItem)
147 		{
148 			currItem->setXYPos(OldX, OldY, true);
149 			currItem->BoundingX = OldBX;
150 			currItem->BoundingY = OldBY;
151 		}
152 	}
153 }
154 
drawPageItems(ScPainterExBase * painter,ScPage * page,ScLayer & layer,QRect clip)155 void ScPageOutput::drawPageItems(ScPainterExBase *painter, ScPage *page, ScLayer& layer, QRect clip)
156 {
157 	PageItem *currItem;
158 	if (m_doc->Items->count() <= 0)
159 		return;
160 	if (!layer.isViewable || !layer.isPrintable)
161 		return;
162 	int docCurrPageNo = static_cast<int>(page->pageNr());
163 	for (int it = 0; it < m_doc->Items->count(); ++it)
164 	{
165 		currItem = m_doc->Items->at(it);
166 		if (currItem->m_layerID != layer.ID)
167 			continue;
168 		if (!currItem->printEnabled())
169 			continue;
170 		if ((m_doc->masterPageMode()) && ((currItem->OwnPage != -1) && (currItem->OwnPage != docCurrPageNo)))
171 			continue;
172 		if (!m_doc->masterPageMode() && !currItem->OnMasterPage.isEmpty())
173 		{
174 			if (currItem->OnMasterPage != page->pageName())
175 				continue;
176 		}
177 		QRectF oldR(currItem->getBoundingRect().adjusted(0.0, 0.0, 1.0, 1.0));
178 		if (clip.intersects(oldR.toRect()))
179 		{
180 			drawItem(currItem, painter, clip);
181 		}
182 	}
183 }
184 
drawItem(PageItem * item,ScPainterExBase * painter,QRect clip)185 void ScPageOutput::drawItem(PageItem* item, ScPainterExBase* painter, QRect clip)
186 {
187 	if (clip.isNull())
188 	{
189 		clip = QRectF(QPointF(m_doc->minCanvasCoordinate.x(), m_doc->minCanvasCoordinate.y()),
190 		              QPointF(m_doc->maxCanvasCoordinate.x(), m_doc->maxCanvasCoordinate.y())).toAlignedRect();
191 	}
192 
193 	drawItem_Pre(item, painter);
194 	PageItem::ItemType itemType = item->itemType();
195 	if (itemType == PageItem::Arc)
196 		drawItem_Arc((PageItem_Arc*) item, painter, clip);
197 	else if (itemType == PageItem::Group)
198 		drawItem_Group((PageItem_Group*) item, painter, clip);
199 	else if (itemType == PageItem::ImageFrame)
200 		drawItem_ImageFrame((PageItem_ImageFrame*) item, painter, clip);
201 	else if (itemType == PageItem::Line)
202 		drawItem_Line((PageItem_Line*) item, painter, clip);
203 	else if (itemType == PageItem::Polygon)
204 		drawItem_Polygon((PageItem_Polygon*) item, painter, clip);
205 	else if (itemType == PageItem::PolyLine)
206 		drawItem_PolyLine((PageItem_PolyLine*) item, painter, clip);
207 	else if (itemType == PageItem::RegularPolygon)
208 		drawItem_RegularPolygon((PageItem_RegularPolygon*) item, painter, clip);
209 	else if (itemType == PageItem::Spiral)
210 		drawItem_Spiral((PageItem_Spiral*) item, painter, clip);
211 	else if (itemType == PageItem::Table)
212 		drawItem_Table((PageItem_Table*) item, painter, clip);
213 	else if (itemType == PageItem::TextFrame || itemType == PageItem::PathText)
214 		drawItem_Text(item, painter, clip);
215 	drawItem_Post(item, painter);
216 }
217 
drawItem_Pre(PageItem * item,ScPainterExBase * painter)218 void ScPageOutput::drawItem_Pre(PageItem* item, ScPainterExBase* painter)
219 {
220 	painter->save();
221 	if (!item->isEmbedded)
222 		painter->translate(item->xPos(), item->yPos());
223 	painter->rotate(item->rotation());
224 	painter->setBlendModeFill(item->fillBlendmode());
225 	painter->setLineWidth(item->lineWidth());
226 	if (item->isGroup())
227 		return;
228 	if (item->GrType == Gradient_Pattern)
229 	{
230 		QString pat = item->pattern();
231 		ScPattern *pattern = m_doc->checkedPattern(pat);
232 		if (!pattern)
233 		{
234 			painter->m_fillGradient = VGradientEx(VGradientEx::linear);
235 			if (item->fillColor() != CommonStrings::None)
236 			{
237 				painter->setBrush(ScColorShade(m_doc->PageColors[item->fillColor()], (int) item->fillShade()));
238 				painter->setFillMode(ScPainterExBase::Solid);
239 			}
240 			else
241 				painter->setFillMode(ScPainterExBase::None);
242 		}
243 		else
244 		{
245 			QTransform patternTransform;
246 			double patternScaleX, patternScaleY, patternOffsetX, patternOffsetY, patternRotation, patternSkewX, patternSkewY;
247 			bool   patternMirrorX, patternMirrorY;
248 			item->patternTransform(patternScaleX, patternScaleY, patternOffsetX, patternOffsetY, patternRotation, patternSkewX, patternSkewY);
249 			item->patternFlip(patternMirrorX, patternMirrorY);
250 			painter->setPattern(pattern, patternScaleX, patternScaleY, patternOffsetX, patternOffsetY, patternRotation, patternSkewX, patternSkewY, patternMirrorX, patternMirrorY);
251 			painter->setFillMode(ScPainterExBase::Pattern);
252 		}
253 	}
254 	else if (item->GrType == Gradient_4Colors)
255 	{
256 		painter->setFillMode(ScPainterExBase::Gradient);
257 		FPoint pG1 = FPoint(0, 0);
258 		FPoint pG2 = FPoint(item->width(), 0);
259 		FPoint pG3 = FPoint(item->width(), item->height());
260 		FPoint pG4 = FPoint(0, item->height());
261 		ScColorShade col1(m_doc->PageColors[item->GrColorP1], item->GrCol1Shade);
262 		ScColorShade col2(m_doc->PageColors[item->GrColorP2], item->GrCol2Shade);
263 		ScColorShade col3(m_doc->PageColors[item->GrColorP3], item->GrCol3Shade);
264 		ScColorShade col4(m_doc->PageColors[item->GrColorP4], item->GrCol4Shade);
265 		painter->set4ColorGeometry(pG1, pG2, pG3, pG4, item->GrControl1, item->GrControl2, item->GrControl3, item->GrControl4);
266 		painter->set4ColorColors(col1, col2, col3, col4);
267 	}
268 	else if (item->GrType != 0)
269 	{
270 		QString gradientVal = item->gradient();
271 		if ((!gradientVal.isEmpty()) && (!m_doc->docGradients.contains(gradientVal)))
272 			gradientVal = "";
273 		if (!(gradientVal.isEmpty()) && (m_doc->docGradients.contains(gradientVal)))
274 			painter->m_fillGradient = VGradientEx(m_doc->docGradients[gradientVal], *m_doc);
275 		if ((painter->m_fillGradient.stops() < 2) && (item->GrType < Gradient_4Colors)) // fall back to solid filling if there are not enough colorstops in the gradient.
276 		{
277 			if (item->fillColor() != CommonStrings::None)
278 			{
279 				painter->setBrush(ScColorShade(m_doc->PageColors[item->fillColor()], (int) item->fillShade()));
280 				painter->setFillMode(ScPainterExBase::Solid);
281 			}
282 			else
283 				painter->setFillMode(ScPainterExBase::None);
284 		}
285 		else
286 		{
287 			FPoint fpStart(item->GrStartX, item->GrStartY), fpEnd(item->GrEndX, item->GrEndY);
288 			FPoint fpFocal(item->GrFocalX, item->GrFocalY);
289 			painter->setFillMode(ScPainterExBase::Gradient);
290 			painter->m_fillGradient = VGradientEx(item->fill_gradient, *m_doc);
291 			switch (item->GrType)
292 			{
293 				case 1:
294 				case 2:
295 				case 3:
296 				case 4:
297 				case 6:
298 					painter->setGradient(VGradientEx::linear, fpStart, fpEnd, fpStart, item->GrScale, item->GrSkew);
299 					break;
300 				case 5:
301 				case 7:
302 					painter->setGradient(VGradientEx::radial, fpStart, fpEnd, fpFocal, item->GrScale, item->GrSkew);
303 					break;
304 				case 10:
305 					painter->setFillMode(ScPainterExBase::Gradient);
306 					painter->setDiamondGeometry(FPoint(0, 0), FPoint(item->width(), 0), FPoint(item->width(), item->height()), FPoint(0, item->height()),
307 					                            item->GrControl1, item->GrControl2, item->GrControl3, item->GrControl4, item->GrControl5);
308 					break;
309 				case 11:
310 				case 13:
311 					painter->setFillMode(ScPainterExBase::Gradient);
312 					painter->setMeshGradient(FPoint(0, 0), FPoint(item->width(), 0), FPoint(item->width(), item->height()), FPoint(0, item->height()), item->meshGradientArray);
313 					break;
314 				case 12:
315 					painter->setFillMode(ScPainterExBase::Gradient);
316 					painter->setMeshGradient(FPoint(0, 0), FPoint(item->width(), 0), FPoint(item->width(), item->height()), FPoint(0, item->height()), item->meshGradientPatches);
317 					break;
318 			}
319 		}
320 	}
321 	else
322 	{
323 		painter->m_fillGradient = VGradientEx(VGradientEx::linear);
324 		if (item->fillColor() != CommonStrings::None)
325 		{
326 			painter->setBrush(ScColorShade(m_doc->PageColors[item->fillColor()], (int) item->fillShade()));
327 			painter->setFillMode(ScPainterExBase::Solid);
328 		}
329 		else
330 			painter->setFillMode(ScPainterExBase::None);
331 	}
332 	if (item->lineColor() != CommonStrings::None)
333 	{
334 		if ((item->lineWidth() == 0) && !item->asLine())
335 			painter->setLineWidth(0);
336 		else
337 		{
338 			ScColorShade tmp(m_doc->PageColors[item->lineColor()], (int) item->lineShade());
339 			painter->setPen(tmp , item->lineWidth(), item->PLineArt, item->PLineEnd, item->PLineJoin);
340 			if (item->DashValues.count() != 0)
341 				painter->setDash(item->DashValues, item->DashOffset);
342 		}
343 	}
344 	else
345 		painter->setLineWidth(0);
346 	painter->setBrushOpacity(1.0 - item->fillTransparency());
347 	painter->setPenOpacity(1.0 - item->lineTransparency());
348 	painter->setFillRule(item->fillRule);
349 
350 	if ((item->GrMask == GradMask_Linear) || (item->GrMask == GradMask_Radial) || (item->GrMask == GradMask_LinearLumAlpha) || (item->GrMask == GradMask_RadialLumAlpha))
351 	{
352 		QString gradientMaskVal = item->gradientMaskVal;
353 		FPoint fpMaskStart(item->GrMaskStartX, item->GrMaskStartY);
354 		FPoint fpMaskEnd(item->GrMaskEndX, item->GrMaskEndY);
355 		FPoint fpMaskFocal(item->GrMaskFocalX, item->GrMaskFocalY);
356 		if ((item->GrMask == GradMask_Linear) || (item->GrMask == GradMask_Radial))
357 			painter->setMaskMode(1);
358 		else
359 			painter->setMaskMode(3);
360 		if ((!gradientMaskVal.isEmpty()) && (!m_doc->docGradients.contains(gradientMaskVal)))
361 			gradientMaskVal = "";
362 		if (!(gradientMaskVal.isEmpty()) && (m_doc->docGradients.contains(gradientMaskVal)))
363 			painter->m_maskGradient = VGradientEx(m_doc->docGradients[gradientMaskVal], *m_doc);
364 		if ((item->GrMask == GradMask_Linear) || (item->GrMask == GradMask_LinearLumAlpha))
365 			painter->setGradientMask(VGradientEx::linear, fpMaskStart, fpMaskEnd, fpMaskStart, item->GrMaskScale, item->GrMaskSkew);
366 		else
367 			painter->setGradientMask(VGradientEx::radial, fpMaskStart, fpMaskEnd, fpMaskFocal, item->GrMaskScale, item->GrMaskSkew);
368 	}
369 	else if ((item->GrMask == GradMask_Pattern) || (item->GrMask == GradMask_PatternLumAlpha) || (item->GrMask == GradMask_PatternLumAlphaInverted) || (item->GrMask == GradMask_PatternInverted))
370 	{
371 		QString patternMaskVal = item->patternMaskVal;
372 		ScPattern *patternMask = m_doc->checkedPattern(patternMaskVal);
373 		if (patternMask)
374 		{
375 			painter->setPatternMask(patternMask, item->patternMaskScaleX, item->patternMaskScaleY, item->patternMaskOffsetX, item->patternMaskOffsetY,
376 				                    item->patternMaskRotation, item->patternMaskSkewX, item->patternMaskSkewY, item->patternMaskMirrorX, item->patternMaskMirrorY);
377 			if (item->GrMask == GradMask_Pattern)
378 				painter->setMaskMode(2);
379 			else if (item->GrMask == GradMask_PatternLumAlpha)
380 				painter->setMaskMode(4);
381 			else if (item->GrMask == GradMask_PatternLumAlphaInverted)
382 				painter->setMaskMode(5);
383 			else
384 				painter->setMaskMode(6);
385 		}
386 		else
387 		{
388 			painter->setMaskMode(0);
389 		}
390 	}
391 	else
392 		painter->setMaskMode(0);
393 }
394 
drawItem_Post(PageItem * item,ScPainterExBase * painter)395 void ScPageOutput::drawItem_Post(PageItem* item, ScPainterExBase* painter)
396 {
397 	bool doStroke = true;
398 	if (!item->isGroup())
399 	{
400 		painter->setMaskMode(0);
401 		if (item->isGroup() || item->isLine() || item->isPathText() || item->isPolyLine() || item->isSpiral() || item->isSymbol() || item->isTable())
402 			doStroke = false;
403 		if (doStroke)
404 		{
405 			painter->setBlendModeStroke(item->lineBlendmode());
406 			painter->setPenOpacity(1.0 - item->lineTransparency());
407 			if ((item->lineColor() != CommonStrings::None)|| (!item->strokePattern().isEmpty()) || (item->strokeGradientType() > 0))
408 			{
409 				ScColorShade tmp(m_doc->PageColors[item->lineColor()], (int) item->lineShade());
410 				painter->setPen(tmp, item->lineWidth(), item->PLineArt, item->PLineEnd, item->PLineJoin);
411 				if (item->DashValues.count() != 0)
412 					painter->setDash(item->DashValues, item->DashOffset);
413 			}
414 			else
415 				painter->setLineWidth(0);
416 			if ((item->itemType() == PageItem::LatexFrame) || (item->itemType() == PageItem::ImageFrame) || (item->itemType() == PageItem::TextFrame) || (item->itemType() == PageItem::OSGFrame))
417 				painter->setupPolygon(&item->PoLine);
418 			if (item->NamedLStyle.isEmpty())
419 			{
420 				QString patternStrokeVal = item->strokePattern();
421 				ScPattern *strokePattern = m_doc->checkedPattern(patternStrokeVal);
422 				if (strokePattern)
423 				{
424 					if (item->patternStrokePath)
425 					{
426 						QPainterPath guidePath = item->PoLine.toQPainterPath(false);
427 						drawStrokePattern(item, painter, guidePath);
428 					}
429 					else
430 					{
431 						painter->setPattern(strokePattern, item->patternStrokeScaleX, item->patternStrokeScaleY, item->patternStrokeOffsetX, item->patternStrokeOffsetY, item->patternStrokeRotation, item->patternStrokeSkewX, item->patternStrokeSkewY, item->patternStrokeMirrorX, item->patternStrokeMirrorY);
432 						painter->setStrokeMode(ScPainterExBase::Pattern);
433 						painter->strokePath();
434 					}
435 				}
436 				else if (item->strokeGradientType() > 0)
437 				{
438 					QString gradientStrokeVal = item->strokeGradient();
439 					if ((!gradientStrokeVal.isEmpty()) && (!m_doc->docGradients.contains(gradientStrokeVal)))
440 						gradientStrokeVal.clear();
441 					if (!(gradientStrokeVal.isEmpty()) && (m_doc->docGradients.contains(gradientStrokeVal)))
442 						painter->m_strokeGradient = VGradientEx(m_doc->docGradients[gradientStrokeVal], *m_doc);
443 					if (painter->m_strokeGradient.stops() < 2) // fall back to solid stroking if there are not enough colorstops in the gradient.
444 					{
445 						if (item->lineColor() != CommonStrings::None)
446 						{
447 							ScColorShade strokeColor(m_doc->PageColors[item->lineColor()], item->lineShade());
448 							painter->setBrush(strokeColor);
449 							painter->setStrokeMode(ScPainterExBase::Solid);
450 						}
451 						else
452 							painter->setStrokeMode(ScPainterExBase::None);
453 					}
454 					else
455 					{
456 						FPoint fpStart(item->GrStrokeStartX, item->GrStrokeStartY);
457 						FPoint fpEnd(item->GrStrokeEndX, item->GrStrokeEndY);
458 						FPoint fpFocal(item->GrStrokeFocalX, item->GrStrokeFocalY);
459 						painter->setStrokeMode(ScPainterExBase::Gradient);
460 						painter->m_strokeGradient = VGradientEx(item->stroke_gradient, *m_doc);
461 						if (item->GrTypeStroke == Gradient_Linear)
462 							painter->setGradient(VGradientEx::linear, fpStart, fpEnd, fpStart, item->GrStrokeScale, item->GrStrokeSkew);
463 						else
464 							painter->setGradient(VGradientEx::radial, fpStart, fpEnd, fpFocal, item->GrStrokeScale, item->GrStrokeSkew);
465 					}
466 					painter->strokePath();
467 				}
468 				else if (item->lineColor() != CommonStrings::None)
469 				{
470 					ScColorShade scColor(m_doc->PageColors[item->lineColor()], item->lineShade());
471 					painter->setStrokeMode(ScPainterExBase::Solid);
472 					painter->setPen(scColor, item->lineWidth(), item->PLineArt, item->PLineEnd, item->PLineJoin);
473 					if (item->DashValues.count() != 0)
474 						painter->setDash(item->DashValues, item->DashOffset);
475 					painter->strokePath();
476 				}
477 			}
478 			else
479 			{
480 				multiLine ml = m_doc->docLineStyles[item->NamedLStyle];
481 				for (int it = ml.size() - 1; it > -1; it--)
482 				{
483 					const SingleLine& sl = ml[it];
484 					if ((sl.Color != CommonStrings::None) && (sl.Width != 0))
485 					{
486 						ScColorShade tmp(m_doc->PageColors[sl.Color], sl.Shade);
487 						painter->setPen(tmp, sl.Width, static_cast<Qt::PenStyle>(sl.Dash),
488 										static_cast<Qt::PenCapStyle>(sl.LineEnd),
489 										static_cast<Qt::PenJoinStyle>(sl.LineJoin));
490 						painter->strokePath();
491 					}
492 				}
493 			}
494 			painter->setBlendModeStroke(0);
495 		}
496 	}
497 	painter->setFillMode(ScPainterExBase::Solid);
498 	painter->setBlendModeFill(0);
499 	painter->setStrokeMode(ScPainterExBase::Solid);
500 	painter->setBlendModeStroke(0);
501 	painter->restore();
502 }
503 
drawItem_Embedded(PageItem * item,ScPainterExBase * p,QRect clip,const CharStyle & style,PageItem * cembedded)504 void ScPageOutput::drawItem_Embedded(PageItem* item, ScPainterExBase *p, QRect clip, const CharStyle& style, PageItem* cembedded)
505 {
506 	if (!cembedded)
507 		return;
508 	QList<PageItem*> emG;
509 	emG.append(cembedded);
510 	for (int em = 0; em < emG.count(); ++em)
511 	{
512 		PageItem* embedded = emG.at(em);
513 		p->save();
514 		double x = embedded->xPos();
515 		double y = embedded->yPos();
516 		embedded->setXPos(embedded->gXpos, true);
517 		embedded->setYPos((embedded->gHeight * (style.scaleV() / 1000.0)) + embedded->gYpos, true);
518 		p->translate((embedded->gXpos * (style.scaleH() / 1000.0)), ( - (embedded->gHeight * (style.scaleV() / 1000.0)) + embedded->gYpos * (style.scaleV() / 1000.0)));
519 		if (style.baselineOffset() != 0)
520 		{
521 			p->translate(0, -embedded->gHeight * (style.baselineOffset() / 1000.0));
522 			embedded->setYPos(embedded->yPos() - embedded->gHeight * (style.baselineOffset() / 1000.0));
523 		}
524 		p->scale(style.scaleH() / 1000.0, style.scaleV() / 1000.0);
525 		double pws = embedded->m_lineWidth;
526 		drawItem_Pre(embedded, p);
527 		switch (embedded->itemType())
528 		{
529 			case PageItem::ImageFrame:
530 			case PageItem::LatexFrame:
531 			case PageItem::TextFrame:
532 			case PageItem::Polygon:
533 			case PageItem::PathText:
534 			case PageItem::Symbol:
535 			case PageItem::Group:
536 			case PageItem::RegularPolygon:
537 			case PageItem::Arc:
538 				drawItem(embedded, p, clip);
539 				break;
540 			case PageItem::Line:
541 			case PageItem::PolyLine:
542 				embedded->m_lineWidth = pws * qMin(style.scaleH() / 1000.0, style.scaleV() / 1000.0);
543 				drawItem(embedded, p, clip);
544 				break;
545 			default:
546 				break;
547 		}
548 		embedded->m_lineWidth = pws * qMin(style.scaleH() / 1000.0, style.scaleV() / 1000.0);
549 		drawItem_Post(embedded, p);
550 		embedded->setXPos(x, true);
551 		embedded->setYPos(y, true);
552 		p->restore();
553 		embedded->m_lineWidth = pws;
554 	}
555 }
556 
drawPattern(PageItem * item,ScPainterExBase * painter,QRect clip)557 void ScPageOutput::drawPattern(PageItem* item, ScPainterExBase* painter, QRect clip)
558 {
559 	double x1, x2, y1, y2;
560 	ScPattern& pattern = m_doc->docPatterns[item->pattern()];
561 	double patternScaleX, patternScaleY, patternOffsetX, patternOffsetY, patternRotation, patternSkewX, patternSkewY;
562 	item->patternTransform(patternScaleX, patternScaleY, patternOffsetX, patternOffsetY, patternRotation, patternSkewX, patternSkewY);
563 
564 	// Compute pattern tansformation matrix and its inverse for converting pattern coordinates
565 	// to pageitem coordinates
566 	QTransform matrix, invMat;
567 	matrix.translate(patternOffsetX, patternOffsetY);
568 	matrix.rotate(patternRotation);
569 	matrix.shear(patternSkewX, patternSkewY);
570 	matrix.scale(pattern.scaleX, pattern.scaleY);
571 	matrix.scale(patternScaleX / 100.0 , patternScaleY / 100.0);
572 	invMat.scale((patternScaleX != 0) ? (100 /patternScaleX) : 1.0, (patternScaleY != 0) ? (100 /patternScaleY) : 1.0);
573 	invMat.scale((pattern.scaleX != 0) ? (1 /pattern.scaleX) : 1.0, (pattern.scaleY != 0) ? (1 /pattern.scaleY) : 1.0);
574 	invMat.rotate(-patternRotation);
575 	invMat.translate(-patternOffsetX, -patternOffsetY);
576 
577 	// Compute bounding box in which pattern item will be drawn
578 	double width  = item->width();
579 	double height = item->height();
580 	double rot    = patternRotation - floor(patternRotation / 90) * 90;
581 	double ctheta = cos(rot * M_PI / 180);
582 	double stheta = sin(rot * M_PI / 180);
583 	QRectF  itemRect(0.0, 0.0, item->width(), item->height());
584 	QPointF pa(width * stheta * stheta, -width * stheta * ctheta);
585 	QPointF pb(width + height * ctheta * stheta, height * stheta * stheta);
586 	QPointF pc(-height * ctheta * stheta, height * ctheta * ctheta);
587 	QPointF pd(width * ctheta * ctheta, height + width * ctheta * stheta);
588 	QPointF ipa = invMat.map(pa), ipb = invMat.map(pb);
589 	QPointF ipc = invMat.map(pc), ipd = invMat.map(pd);
590 
591 	painter->save();
592 	if (!item->imageClip.empty())
593 	{
594 		painter->setupPolygon(&item->imageClip);
595 		painter->setClipPath();
596 	}
597 	painter->setupPolygon(&item->PoLine);
598 	painter->setClipPath();
599 	for (int index = 0; index < pattern.items.count(); index++)
600 	{
601 		QRectF itRect;
602 		PageItem* it = pattern.items.at(index);
603 
604 		painter->save();
605 		painter->translate(patternOffsetX, patternOffsetY);
606 		painter->rotate(patternRotation);
607 		painter->scale(pattern.scaleX, pattern.scaleY);
608 		painter->scale(patternScaleX / 100.0, patternScaleY / 100.0);
609 
610 		double patWidth  = (pattern.width != 0.0) ? pattern.width : 1.0;
611 		double patHeight = (pattern.height != 0.0) ? pattern.height : 1.0;
612 		double kxa = (ipa.x() - it->gXpos) / patWidth;
613 		double kxb = (ipb.x() - it->gXpos) / patWidth;
614 		double kxc = (ipc.x() - it->gXpos) / patWidth;
615 		double kxd = (ipd.x() - it->gXpos) / patWidth;
616 		double kya = (ipa.y() - it->gYpos) / patHeight;
617 		double kyb = (ipb.y() - it->gYpos) / patHeight;
618 		double kyc = (ipc.y() - it->gYpos) / patHeight;
619 		double kyd = (ipd.y() - it->gYpos) / patHeight;
620 		int kxMin  = (int) floor(qMin(qMin(kxa, kxb), qMin(kxc, kxd)));
621 		int kxMax  = (int) ceil (qMax(qMax(kxa, kxb), qMax(kxc, kxd)));
622 		int kyMin  = (int) floor(qMin(qMin(kya, kyb), qMin(kyc, kyd)));
623 		int kyMax  = (int) ceil (qMax(qMax(kya, kyb), qMax(kyc, kyd)));
624 
625 		double itx = it->xPos();
626 		double ity = it->yPos();
627 		double itPosX = it->gXpos, itPosY = it->gYpos;
628 		for (int kx = kxMin; kx <= kxMax; kx++)
629 		{
630 			for (int ky = kyMin; ky <= kyMax; ky++)
631 			{
632 				itPosX = it->gXpos + kx * pattern.width;
633 				itPosY = it->gYpos + ky * pattern.height;
634 				it->setXYPos(itPosX, itPosY);
635 				it->getBoundingRect(&x1, &y1, &x2, &y2);
636 				itRect.setCoords(x1, y1, x2, y2);
637 				itRect = matrix.mapRect(itRect);
638 				if (itRect.intersects(itemRect))
639 					drawItem(it, painter, clip);
640 			}
641 		}
642 		it->setXYPos(itx, ity);
643 		painter->restore();
644 	}
645 	painter->restore();
646 }
647 
drawStrokePattern(PageItem * item,ScPainterExBase * painter,const QPainterPath & path)648 void ScPageOutput::drawStrokePattern(PageItem* item, ScPainterExBase* painter, const QPainterPath& path)
649 {
650 
651 }
652 
drawItem_Arc(PageItem_Arc * item,ScPainterExBase * painter,QRect clip)653 void ScPageOutput::drawItem_Arc(PageItem_Arc* item , ScPainterExBase* painter, QRect clip)
654 {
655 	painter->setupPolygon(&item->PoLine);
656 	fillPath(item, painter, clip);
657 }
658 
drawItem_Group(PageItem_Group * item,ScPainterExBase * painter,QRect clip)659 void ScPageOutput::drawItem_Group(PageItem_Group* item, ScPainterExBase* painter, QRect clip)
660 {
661 	if (item->groupItemList.isEmpty())
662 		return;
663 
664 	painter->save();
665 	if (item->imageFlippedH())
666 	{
667 		painter->translate(item->width(), 0);
668 		painter->scale(-1, 1);
669 	}
670 	if (item->imageFlippedV())
671 	{
672 		painter->translate(0, item->height());
673 		painter->scale(1, -1);
674 	}
675 	/*if ((maskType() == 1) || (maskType() == 2) || (maskType() == 4) || (maskType() == 5))
676 	{
677 		if ((maskType() == 1) || (maskType() == 2))
678 			painter->setMaskMode(1);
679 		else
680 			painter->setMaskMode(3);
681 		if ((!gradientMask().isEmpty()) && (!m_Doc->docGradients.contains(gradientMask())))
682 			gradientMaskVal = "";
683 		if (!(gradientMask().isEmpty()) && (m_Doc->docGradients.contains(gradientMask())))
684 			mask_gradient = m_Doc->docGradients[gradientMask()];
685 		painter->mask_gradient = mask_gradient;
686 		if ((maskType() == 1) || (maskType() == 4))
687 			painter->setGradientMask(VGradient::linear, FPoint(GrMaskStartX, GrMaskStartY), FPoint(GrMaskEndX, GrMaskEndY), FPoint(GrMaskStartX, GrMaskStartY), GrMaskScale, GrMaskSkew);
688 		else
689 			painter->setGradientMask(VGradient::radial, FPoint(GrMaskStartX, GrMaskStartY), FPoint(GrMaskEndX, GrMaskEndY), FPoint(GrMaskFocalX, GrMaskFocalY), GrMaskScale, GrMaskSkew);
690 	}
691 	else if ((maskType() == 3) || (maskType() == 6) || (maskType() == 7) || (maskType() == 8))
692 	{
693 		if ((patternMask().isEmpty()) || (!m_Doc->docPatterns.contains(patternMask())))
694 			painter->setMaskMode(0);
695 		else
696 		{
697 			double scw = Width / groupWidth;
698 			double sch = Height / groupHeight;
699 			painter->setPatternMask(&m_Doc->docPatterns[patternMask()], patternMaskScaleX * scw, patternMaskScaleY * sch, patternMaskOffsetX, patternMaskOffsetY, patternMaskRotation, patternMaskSkewX, patternMaskSkewY, patternMaskMirrorX, patternMaskMirrorY);
700 			if (maskType() == 3)
701 				painter->setMaskMode(2);
702 			else if (maskType() == 6)
703 				painter->setMaskMode(4);
704 			else if (maskType() == 7)
705 				painter->setMaskMode(5);
706 			else
707 				painter->setMaskMode(6);
708 		}
709 	}
710 	else*/
711 		painter->setMaskMode(0);
712 	painter->setFillRule(item->fillRule);
713 	//painter->beginLayer(1.0 - fillTransparency(), fillBlendmode(), &PoLine);
714 	painter->setMaskMode(0);
715 	painter->scale(item->width() / item->groupWidth, item->height() / item->groupHeight);
716 	for (int em = 0; em < item->groupItemList.count(); ++em)
717 	{
718 		PageItem* embedded = item->groupItemList.at(em);
719 		painter->save();
720 		painter->translate(embedded->gXpos, embedded->gYpos);
721 		embedded->savedOwnPage = embedded->OwnPage;
722 		embedded->OwnPage = item->OwnPage;
723 		embedded->isEmbedded = true;
724 		embedded->invalidateLayout();
725 		drawItem(embedded, painter, QRect());
726 		embedded->isEmbedded = false;
727 		embedded->OwnPage = embedded->savedOwnPage;
728 		painter->restore();
729 	}
730 	//painter->endLayer();
731 	painter->restore();
732 }
733 
drawItem_ImageFrame(PageItem_ImageFrame * item,ScPainterExBase * painter,QRect clip)734 void ScPageOutput::drawItem_ImageFrame(PageItem_ImageFrame* item, ScPainterExBase* painter, QRect clip)
735 {
736 	ScPainterExBase::ImageMode mode = ScPainterExBase::rgbImages;
737 	if ((item->fillColor() != CommonStrings::None) || (item->GrType != 0))
738 	{
739 		painter->setupPolygon(&item->PoLine);
740 		fillPath(item, painter, clip);
741 	}
742 	if (item->Pfile.isEmpty())
743 	{
744 		/*painter->setPen(ScColorShade(Qt::black, 100), 1, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin);
745 		painter->drawLine(FPoint(0, 0), FPoint(item->width(), item->height()));
746 		painter->drawLine(FPoint(0, item->height()), FPoint(item->width(), 0));*/
747 	}
748 	else
749 	{
750 		if ((!item->imageVisible()) || (!item->imageIsAvailable))
751 		{
752 			/*painter->setPen(ScColorShade(Qt::red, 100), 1, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin);
753 			painter->drawLine(FPoint(0, 0), FPoint(item->width(), item->height()));
754 			painter->drawLine(FPoint(0, item->height()), FPoint(item->width(), 0));*/
755 		}
756 		else
757 		{
758 			ScImage scImg;
759 			ScImage* pImage = nullptr;
760 			double imScaleX = item->imageXScale();
761 			double imScaleY = item->imageYScale();
762 			if (m_reloadImages)
763 			{
764 				bool dummy;
765 				bool useCmyk = false;
766 				ScPainterExBase::ImageMode imageMode = painter->imageMode();
767 				if (imageMode == ScPainterExBase::cmykImages)
768 					useCmyk = true;
769 				QFileInfo fInfo(item->Pfile);
770 				QString ext = fInfo.suffix();
771 				CMSettings cmsSettings(item->doc(), item->ImageProfile, item->ImageIntent);
772 				cmsSettings.allowColorManagement(m_useProfiles);
773 				cmsSettings.setUseEmbeddedProfile(item->UseEmbedded);
774 				scImg.imgInfo.valid = false;
775 				scImg.imgInfo.clipPath = "";
776 				scImg.imgInfo.PDSpathData.clear();
777 				scImg.imgInfo.layerInfo.clear();
778 				scImg.imgInfo.RequestProps = item->pixm.imgInfo.RequestProps;
779 				scImg.imgInfo.isRequest = item->pixm.imgInfo.isRequest;
780 				scImg.loadPicture(item->Pfile, item->pixm.imgInfo.actualPageNumber, cmsSettings, translateImageModeToRequest(imageMode), m_imageRes, &dummy);
781 				if (extensionIndicatesEPSorPS(ext) || extensionIndicatesPDF(ext))
782 				{
783 					imScaleX *= (72.0 / (double) m_imageRes);
784 					imScaleY *= (72.0 / (double) m_imageRes);
785 				}
786 				scImg.applyEffect(item->effectsInUse, m_doc->PageColors, useCmyk);
787 				mode = imageMode;
788 				pImage = &scImg;
789 			}
790 			else
791 				pImage = &item->pixm;
792 
793 			painter->save();
794 			if (!item->imageClip.empty())
795 			{
796 				painter->setupPolygon(&item->imageClip);
797 				painter->setClipPath();
798 			}
799 			painter->setupPolygon(&item->PoLine);
800 			painter->setClipPath();
801 			if (item->imageFlippedH())
802 			{
803 				painter->translate(item->width(), 0);
804 				painter->scale(-1, 1);
805 			}
806 			if (item->imageFlippedV())
807 			{
808 				painter->translate(0, item->height());
809 				painter->scale(1, -1);
810 			}
811 			painter->translate(item->imageXOffset() * item->imageXScale(), item->imageYOffset() * item->imageYScale());
812 			painter->rotate(item->imageRotation());
813 			painter->scale(imScaleX, imScaleY);
814 			if (pImage->imgInfo.lowResType != 0)
815 				painter->scale(pImage->imgInfo.lowResScale, pImage->imgInfo.lowResScale);
816 			painter->drawImage(pImage, mode);
817 			painter->restore();
818 		}
819 	}
820 }
821 
drawItem_Line(PageItem_Line * item,ScPainterExBase * painter,QRect clip)822 void ScPageOutput::drawItem_Line(PageItem_Line* item, ScPainterExBase* painter, QRect clip)
823 {
824 	int startArrowIndex = item->startArrowIndex();
825 	int endArrowIndex = item->endArrowIndex();
826 
827 	if (item->NamedLStyle.isEmpty())
828 	{
829 		QString patternStrokeVal = item->strokePattern();
830 		ScPattern *strokePattern = m_doc->checkedPattern(patternStrokeVal);
831 		if (strokePattern)
832 		{
833 			if (item->patternStrokePath)
834 			{
835 				QPainterPath guidePath = item->PoLine.toQPainterPath(false);
836 				guidePath.moveTo(0, 0);
837 				guidePath.lineTo(item->width(), 0);
838 				drawStrokePattern(item, painter, guidePath);
839 			}
840 			else
841 			{
842 				painter->setPattern(strokePattern, item->patternStrokeScaleX, item->patternStrokeScaleY, item->patternStrokeOffsetX, item->patternStrokeOffsetY, item->patternStrokeRotation, item->patternStrokeSkewX, item->patternStrokeSkewY, item->patternStrokeMirrorX, item->patternStrokeMirrorY);
843 				painter->setStrokeMode(ScPainterExBase::Pattern);
844 				painter->strokePath();
845 			}
846 		}
847 		else if (item->strokeGradientType() > 0)
848 		{
849 			QString gradientStrokeVal = item->strokeGradient();
850 			if ((!gradientStrokeVal.isEmpty()) && (!m_doc->docGradients.contains(gradientStrokeVal)))
851 				gradientStrokeVal.clear();
852 			if (!(gradientStrokeVal.isEmpty()) && (m_doc->docGradients.contains(gradientStrokeVal)))
853 				painter->m_strokeGradient = VGradientEx(m_doc->docGradients[gradientStrokeVal], *m_doc);
854 			if (painter->m_strokeGradient.stops() < 2) // fall back to solid stroking if there are not enough colorstops in the gradient.
855 			{
856 				if (item->lineColor() != CommonStrings::None)
857 				{
858 					ScColorShade strokeColor(m_doc->PageColors[item->lineColor()], item->lineShade());
859 					painter->setBrush(strokeColor);
860 					painter->setStrokeMode(ScPainterExBase::Solid);
861 				}
862 				else
863 					painter->setStrokeMode(ScPainterExBase::None);
864 			}
865 			else
866 			{
867 				FPoint fpStart(item->GrStrokeStartX, item->GrStrokeStartY);
868 				FPoint fpEnd(item->GrStrokeEndX, item->GrStrokeEndY);
869 				FPoint fpFocal(item->GrStrokeFocalX, item->GrStrokeFocalY);
870 				painter->setStrokeMode(ScPainterExBase::Gradient);
871 				painter->m_strokeGradient = VGradientEx(item->stroke_gradient, *m_doc);
872 				if (item->GrTypeStroke == Gradient_Linear)
873 					painter->setGradient(VGradientEx::linear, fpStart, fpEnd, fpStart, item->GrStrokeScale, item->GrStrokeSkew);
874 				else
875 					painter->setGradient(VGradientEx::radial, fpStart, fpEnd, fpFocal, item->GrStrokeScale, item->GrStrokeSkew);
876 			}
877 			painter->drawLine(FPoint(0, 0), FPoint(item->width(), 0));
878 		}
879 		else if (item->lineColor() != CommonStrings::None)
880 		{
881 			ScColorShade scColor(m_doc->PageColors[item->lineColor()], item->lineShade());
882 			painter->setStrokeMode(ScPainterExBase::Solid);
883 			painter->setPen(scColor, item->lineWidth(), item->PLineArt, item->PLineEnd, item->PLineJoin);
884 			if (item->DashValues.count() != 0)
885 				painter->setDash(item->DashValues, item->DashOffset);
886 			painter->drawLine(FPoint(0, 0), FPoint(item->width(), 0));
887 		}
888 	}
889 	else
890 	{
891 		painter->setStrokeMode(ScPainterExBase::Solid);
892 		multiLine ml = m_doc->docLineStyles[item->NamedLStyle];
893 		for (int it = ml.size() - 1; it > -1; it--)
894 		{
895 			const SingleLine& sl = ml[it];
896 			if ((sl.Color != CommonStrings::None) && (sl.Width != 0))
897 			{
898 				ScColorShade tmp(m_doc->PageColors[sl.Color], sl.Shade);
899 				painter->setPen(tmp, sl.Width, static_cast<Qt::PenStyle>(sl.Dash),
900 						static_cast<Qt::PenCapStyle>(sl.LineEnd),
901 						static_cast<Qt::PenJoinStyle>(sl.LineJoin));
902 				painter->drawLine(FPoint(0, 0), FPoint(item->width(), 0));
903 			}
904 		}
905 	}
906 	if (startArrowIndex != 0)
907 	{
908 		QTransform arrowTrans;
909 		arrowTrans.translate(0, 0);
910 		arrowTrans.scale(-1, 1);
911 		drawArrow(painter, item, arrowTrans, startArrowIndex);
912 	}
913 	if (endArrowIndex != 0)
914 	{
915 		QTransform arrowTrans;
916 		arrowTrans.translate(item->width(), 0);
917 		drawArrow(painter, item, arrowTrans, endArrowIndex);
918 	}
919 }
920 
921 class ScPageOutputPainter: public TextLayoutPainter
922 {
923 private:
924 	PageItem* m_item;
925 	ScPainterExBase* m_painter;
926 	ScPageOutput* m_scpage;
927 
setupState()928 	void setupState()
929 	{
930 		m_painter->setLineWidth(strokeWidth());
931 		ScColorShade fill(m_item->doc()->PageColors[fillColor().color], fillColor().shade);
932 		m_painter->setBrush(fill);
933 		ScColorShade stroke(m_item->doc()->PageColors[strokeColor().color], strokeColor().shade);
934 		m_painter->setPen(stroke, strokeWidth(), Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin);
935 
936 		if (matrix() != QTransform())
937 		{
938 			m_painter->setWorldMatrix(matrix() * m_painter->worldMatrix());
939 		}
940 	}
941 
942 public:
ScPageOutputPainter(PageItem * item,ScPainterExBase * painter,ScPageOutput * scpage)943 	ScPageOutputPainter(PageItem* item, ScPainterExBase* painter, ScPageOutput* scpage)
944 		: m_item(item)
945 		, m_painter(painter)
946 		, m_scpage(scpage)
947 	{}
948 
translate(double xp,double yp)949 	void translate(double xp, double yp) override
950 	{
951 		TextLayoutPainter::translate(xp, yp);
952 		m_painter->translate(xp, yp);
953 	}
954 
save()955 	void save() override
956 	{
957 		TextLayoutPainter::save();
958 		m_painter->save();
959 	}
960 
restore()961 	void restore() override
962 	{
963 		TextLayoutPainter::restore();
964 		m_painter->restore();
965 	}
966 
setScale(double h,double v)967 	void setScale(double h, double v) override
968 	{
969 		TextLayoutPainter::setScale(h, v);
970 		m_painter->scale(h, v);
971 	}
972 
drawGlyph(const GlyphCluster & gc)973 	void drawGlyph(const GlyphCluster& gc) override
974 	{
975 		if (gc.isControlGlyphs())
976 			return;
977 
978 		m_painter->save();
979 		bool fr = m_painter->fillRule();
980 		int fm = m_painter->fillMode();
981 
982 		m_painter->setFillRule(false);
983 		m_painter->setFillMode(ScPainterExBase::Solid);
984 
985 		setupState();
986 
987 		double sizeFactor = fontSize() / 10.0;
988 		QVector<FPointArray> outlines = gc.glyphClusterOutline();
989 		const QList<GlyphLayout>& glyphs = gc.glyphs();
990 		for (int i = 0; i < glyphs.count(); ++i)
991 		{
992 			const FPointArray& outline = outlines.at(i);
993 			const GlyphLayout& gl = glyphs.at(i);
994 			m_painter->save();
995 			m_painter->translate(gl.xoffset, - (fontSize() * gl.scaleV) + gl.yoffset);
996 			m_painter->scale(gl.scaleH * sizeFactor, gl.scaleV * sizeFactor);
997 			m_painter->setupPolygon(&outline, true);
998 			if (outline.size() > 3)
999 				m_painter->fillPath();
1000 			m_painter->restore();
1001 			m_painter->translate(gl.xadvance * gl.scaleH, 0.0);
1002 		}
1003 
1004 		m_painter->setFillMode(fm);
1005 		m_painter->setFillRule(fr);
1006 		m_painter->restore();
1007 	}
1008 
drawGlyphOutline(const GlyphCluster & gc,bool fill)1009 	void drawGlyphOutline(const GlyphCluster& gc, bool fill) override
1010 	{
1011 		if (gc.isControlGlyphs())
1012 			return;
1013 
1014 		if (fill)
1015 			drawGlyph(gc);
1016 
1017 		m_painter->save();
1018 		bool fr = m_painter->fillRule();
1019 		m_painter->setFillRule(false);
1020 
1021 		setupState();
1022 		double current_x = 0.0;
1023 		for (const GlyphLayout& gl : gc.glyphs())
1024 		{
1025 			m_painter->save();
1026 			m_painter->translate(gl.xoffset + current_x, -(fontSize() * gc.scaleV()) + gl.yoffset);
1027 
1028 			FPointArray outline = font().glyphOutline(gl.glyph);
1029 			double scaleH = gl.scaleH * fontSize() / 10.0;
1030 			double scaleV = gl.scaleV * fontSize() / 10.0;
1031 			QTransform trans;
1032 			trans.scale(scaleH, scaleV);
1033 			outline.map(trans);
1034 			m_painter->setupPolygon(&outline, true);
1035 			if (outline.size() > 3)
1036 			{
1037 				m_painter->setLineWidth(strokeWidth());
1038 				m_painter->strokePath();
1039 			}
1040 			m_painter->restore();
1041 			current_x += gl.xadvance * gl.scaleH;
1042 		}
1043 
1044 		m_painter->setFillRule(fr);
1045 		m_painter->restore();
1046 	}
1047 
drawLine(QPointF start,QPointF end)1048 	void drawLine(QPointF start, QPointF end) override
1049 	{
1050 		m_painter->save();
1051 		setupState();
1052 		m_painter->drawLine(start, end);
1053 		m_painter->restore();
1054 	}
1055 
drawRect(QRectF rect)1056 	void drawRect(QRectF rect) override
1057 	{
1058 		m_painter->save();
1059 		setupState();
1060 		m_painter->setFillMode(ScPainterExBase::Solid);
1061 		m_painter->setStrokeMode(ScPainterExBase::Solid);
1062 		m_painter->drawRect(rect.x(), rect.y(), rect.width(), rect.height());
1063 		m_painter->restore();
1064 	}
1065 
drawObject(PageItem * embedded)1066 	void drawObject(PageItem* embedded) override
1067 	{
1068 		QRect cullingArea;
1069 		if (!embedded)
1070 			return;
1071 
1072 		m_painter->save();
1073 		double pws = embedded->m_lineWidth;
1074 
1075 		embedded->invalid = true;
1076 		m_scpage->drawItem_Pre(embedded, m_painter);
1077 
1078 		switch (embedded->itemType())
1079 		{
1080 		case PageItem::ImageFrame:
1081 		case PageItem::TextFrame:
1082 		case PageItem::LatexFrame:
1083 		case PageItem::OSGFrame:
1084 		case PageItem::Polygon:
1085 		case PageItem::PathText:
1086 		case PageItem::Symbol:
1087 		case PageItem::Group:
1088 		case PageItem::RegularPolygon:
1089 		case PageItem::Arc:
1090 		case PageItem::Table:
1091 			m_scpage->drawItem(embedded, m_painter, cullingArea);
1092 			break;
1093 		case PageItem::Line:
1094 		case PageItem::PolyLine:
1095 		case PageItem::Spiral:
1096 			embedded->m_lineWidth = pws * qMin(scaleH(), scaleV());
1097 			m_scpage->drawItem(embedded, m_painter, cullingArea);
1098 			break;
1099 		default:
1100 			break;
1101 		}
1102 
1103 		embedded->m_lineWidth = pws * qMin(scaleH(), scaleV());
1104 		m_scpage->drawItem_Post(embedded, m_painter);
1105 		embedded->m_lineWidth = pws;
1106 		m_painter->restore();
1107 	}
1108 };
1109 
drawItem_Polygon(PageItem_Polygon * item,ScPainterExBase * painter,QRect clip)1110 void ScPageOutput::drawItem_Polygon(PageItem_Polygon* item , ScPainterExBase* painter, QRect clip)
1111 {
1112 	painter->setupPolygon(&item->PoLine);
1113 	fillPath(item, painter, clip);
1114 }
1115 
drawItem_PolyLine(PageItem_PolyLine * item,ScPainterExBase * painter,QRect clip)1116 void ScPageOutput::drawItem_PolyLine(PageItem_PolyLine* item, ScPainterExBase* painter, QRect clip)
1117 {
1118 	if (item->PoLine.size() < 4)
1119 		return;
1120 
1121 	int startArrowIndex = item->startArrowIndex();
1122 	int endArrowIndex = item->endArrowIndex();
1123 
1124 	if ((item->fillColor() != CommonStrings::None) || (item->GrType != 0))
1125 	{
1126 		FPointArray cli;
1127 		FPoint Start;
1128 		bool firstp = true;
1129 		for (int n = 0; n < item->PoLine.size()-3; n += 4)
1130 		{
1131 			if (firstp)
1132 			{
1133 				Start = item->PoLine.point(n);
1134 				firstp = false;
1135 			}
1136 			if (item->PoLine.isMarker(n))
1137 			{
1138 				if (n >= 2)
1139 				{
1140 					cli.addPoint(item->PoLine.point(n - 2));
1141 					cli.addPoint(item->PoLine.point(n - 2));
1142 					cli.addPoint(Start);
1143 					cli.addPoint(Start);
1144 					cli.setMarker();
1145 				}
1146 				firstp = true;
1147 				continue;
1148 			}
1149 			cli.addPoint(item->PoLine.point(n));
1150 			cli.addPoint(item->PoLine.point(n+1));
1151 			cli.addPoint(item->PoLine.point(n+2));
1152 			cli.addPoint(item->PoLine.point(n+3));
1153 		}
1154 		if (cli.size() > 2)
1155 		{
1156 			FPoint l1 = cli.point(cli.size()-2);
1157 			cli.addPoint(l1);
1158 			cli.addPoint(l1);
1159 			cli.addPoint(Start);
1160 			cli.addPoint(Start);
1161 		}
1162 		painter->setupPolygon(&cli);
1163 		fillPath(item, painter, clip);
1164 	}
1165 	painter->setupPolygon(&item->PoLine, false);
1166 	if (item->NamedLStyle.isEmpty())
1167 	{
1168 		QString patternStrokeVal = item->strokePattern();
1169 		ScPattern *strokePattern = m_doc->checkedPattern(patternStrokeVal);
1170 		if (strokePattern)
1171 		{
1172 			if (item->patternStrokePath)
1173 			{
1174 				QPainterPath guidePath = item->PoLine.toQPainterPath(false);
1175 				guidePath.moveTo(0, 0);
1176 				guidePath.lineTo(item->width(), 0);
1177 				drawStrokePattern(item, painter, guidePath);
1178 			}
1179 			else
1180 			{
1181 				painter->setPattern(strokePattern, item->patternStrokeScaleX, item->patternStrokeScaleY, item->patternStrokeOffsetX, item->patternStrokeOffsetY, item->patternStrokeRotation, item->patternStrokeSkewX, item->patternStrokeSkewY, item->patternStrokeMirrorX, item->patternStrokeMirrorY);
1182 				painter->setStrokeMode(ScPainterExBase::Pattern);
1183 				painter->strokePath();
1184 			}
1185 		}
1186 		else if (item->strokeGradientType() > 0)
1187 		{
1188 			QString gradientStrokeVal = item->strokeGradient();
1189 			if ((!gradientStrokeVal.isEmpty()) && (!m_doc->docGradients.contains(gradientStrokeVal)))
1190 				gradientStrokeVal.clear();
1191 			if (!(gradientStrokeVal.isEmpty()) && (m_doc->docGradients.contains(gradientStrokeVal)))
1192 				painter->m_strokeGradient = VGradientEx(m_doc->docGradients[gradientStrokeVal], *m_doc);
1193 			if (painter->m_strokeGradient.stops() < 2) // fall back to solid stroking if there are not enough colorstops in the gradient.
1194 			{
1195 				if (item->lineColor() != CommonStrings::None)
1196 				{
1197 					ScColorShade strokeColor(m_doc->PageColors[item->lineColor()], item->lineShade());
1198 					painter->setBrush(strokeColor);
1199 					painter->setStrokeMode(ScPainterExBase::Solid);
1200 				}
1201 				else
1202 					painter->setStrokeMode(ScPainterExBase::None);
1203 			}
1204 			else
1205 			{
1206 				FPoint fpStart(item->GrStrokeStartX, item->GrStrokeStartY);
1207 				FPoint fpEnd(item->GrStrokeEndX, item->GrStrokeEndY);
1208 				FPoint fpFocal(item->GrStrokeFocalX, item->GrStrokeFocalY);
1209 				painter->setStrokeMode(ScPainterExBase::Gradient);
1210 				painter->m_strokeGradient = VGradientEx(item->stroke_gradient, *m_doc);
1211 				if (item->GrTypeStroke == Gradient_Linear)
1212 					painter->setGradient(VGradientEx::linear, fpStart, fpEnd, fpStart, item->GrStrokeScale, item->GrStrokeSkew);
1213 				else
1214 					painter->setGradient(VGradientEx::radial, fpStart, fpEnd, fpFocal, item->GrStrokeScale, item->GrStrokeSkew);
1215 			}
1216 			painter->strokePath();
1217 		}
1218 		else if (item->lineColor() != CommonStrings::None)
1219 		{
1220 			ScColorShade scColor(m_doc->PageColors[item->lineColor()], item->lineShade());
1221 			painter->setStrokeMode(ScPainterExBase::Solid);
1222 			painter->setPen(scColor, item->lineWidth(), item->PLineArt, item->PLineEnd, item->PLineJoin);
1223 			if (item->DashValues.count() != 0)
1224 				painter->setDash(item->DashValues, item->DashOffset);
1225 			painter->strokePath();
1226 		}
1227 	}
1228 	else
1229 	{
1230 		multiLine ml = m_doc->docLineStyles[item->NamedLStyle];
1231 		for (int it = ml.size() - 1; it > -1; it--)
1232 		{
1233 			const SingleLine& sl = ml[it];
1234 			if (sl.Color != CommonStrings::None)
1235 			{
1236 				ScColorShade tmp(m_doc->PageColors[sl.Color], sl.Shade);
1237 				painter->setPen(tmp, sl.Width, static_cast<Qt::PenStyle>(sl.Dash),
1238 						static_cast<Qt::PenCapStyle>(sl.LineEnd),
1239 						static_cast<Qt::PenJoinStyle>(sl.LineJoin));
1240 				painter->strokePath();
1241 			}
1242 		}
1243 	}
1244 	if (startArrowIndex != 0)
1245 	{
1246 		FPoint Start = item->PoLine.point(0);
1247 		for (int xx = 1; xx < item->PoLine.size(); xx += 2)
1248 		{
1249 			FPoint Vector = item->PoLine.point(xx);
1250 			if ((Start.x() != Vector.x()) || (Start.y() != Vector.y()))
1251 			{
1252 				double r = atan2(Start.y() - Vector.y(), Start.x() - Vector.x()) * (180.0 / M_PI);
1253 				QTransform arrowTrans;
1254 				arrowTrans.translate(Start.x(), Start.y());
1255 				arrowTrans.rotate(r);
1256 				drawArrow(painter, item, arrowTrans, startArrowIndex);
1257 				break;
1258 			}
1259 		}
1260 	}
1261 	if (endArrowIndex != 0)
1262 	{
1263 		FPoint End = item->PoLine.point(item->PoLine.size()-2);
1264 		for (uint xx = item->PoLine.size() - 1; xx > 0; xx -= 2)
1265 		{
1266 			FPoint Vector = item->PoLine.point(xx);
1267 			if ((End.x() != Vector.x()) || (End.y() != Vector.y()))
1268 			{
1269 				double r = atan2(End.y() - Vector.y(), End.x() - Vector.x()) * (180.0 / M_PI);
1270 				QTransform arrowTrans;
1271 				arrowTrans.translate(End.x(), End.y());
1272 				arrowTrans.rotate(r);
1273 				drawArrow(painter, item, arrowTrans, endArrowIndex);
1274 				break;
1275 			}
1276 		}
1277 	}
1278 }
1279 
drawItem_RegularPolygon(PageItem_RegularPolygon * item,ScPainterExBase * painter,QRect clip)1280 void ScPageOutput::drawItem_RegularPolygon(PageItem_RegularPolygon* item, ScPainterExBase* painter, QRect clip)
1281 {
1282 	painter->setupPolygon(&item->PoLine);
1283 	painter->fillPath();
1284 }
1285 
drawItem_Spiral(PageItem_Spiral * item,ScPainterExBase * painter,QRect clip)1286 void ScPageOutput::drawItem_Spiral(PageItem_Spiral* item, ScPainterExBase* painter, QRect clip)
1287 {
1288 	if (item->PoLine.size() < 4)
1289 		return;
1290 
1291 	int startArrowIndex = item->startArrowIndex();
1292 	int endArrowIndex = item->endArrowIndex();
1293 
1294 	if ((item->fillColor() != CommonStrings::None) || (item->GrType != 0))
1295 	{
1296 		FPointArray cli;
1297 		FPoint Start;
1298 		bool firstp = true;
1299 		for (int n = 0; n < item->PoLine.size()-3; n += 4)
1300 		{
1301 			if (firstp)
1302 			{
1303 				Start = item->PoLine.point(n);
1304 				firstp = false;
1305 			}
1306 			if (item->PoLine.isMarker(n))
1307 			{
1308 				cli.addPoint(item->PoLine.point(n-2));
1309 				cli.addPoint(item->PoLine.point(n-2));
1310 				cli.addPoint(Start);
1311 				cli.addPoint(Start);
1312 				cli.setMarker();
1313 				firstp = true;
1314 				continue;
1315 			}
1316 			cli.addPoint(item->PoLine.point(n));
1317 			cli.addPoint(item->PoLine.point(n+1));
1318 			cli.addPoint(item->PoLine.point(n+2));
1319 			cli.addPoint(item->PoLine.point(n+3));
1320 		}
1321 		if (cli.size() > 2)
1322 		{
1323 			FPoint l1 = cli.point(cli.size()-2);
1324 			cli.addPoint(l1);
1325 			cli.addPoint(l1);
1326 			cli.addPoint(Start);
1327 			cli.addPoint(Start);
1328 		}
1329 		painter->setupPolygon(&cli);
1330 		fillPath(item, painter, clip);
1331 	}
1332 	painter->setupPolygon(&item->PoLine, false);
1333 	if (item->NamedLStyle.isEmpty())
1334 	{
1335 		QString patternStrokeVal = item->strokePattern();
1336 		ScPattern *strokePattern = m_doc->checkedPattern(patternStrokeVal);
1337 		if (strokePattern)
1338 		{
1339 			if (item->patternStrokePath)
1340 			{
1341 				QPainterPath guidePath = item->PoLine.toQPainterPath(false);
1342 				guidePath.moveTo(0, 0);
1343 				guidePath.lineTo(item->width(), 0);
1344 				drawStrokePattern(item, painter, guidePath);
1345 			}
1346 			else
1347 			{
1348 				painter->setPattern(strokePattern, item->patternStrokeScaleX, item->patternStrokeScaleY, item->patternStrokeOffsetX, item->patternStrokeOffsetY, item->patternStrokeRotation, item->patternStrokeSkewX, item->patternStrokeSkewY, item->patternStrokeMirrorX, item->patternStrokeMirrorY);
1349 				painter->setStrokeMode(ScPainterExBase::Pattern);
1350 				painter->strokePath();
1351 			}
1352 		}
1353 		else if (item->strokeGradientType() > 0)
1354 		{
1355 			QString gradientStrokeVal = item->strokeGradient();
1356 			if ((!gradientStrokeVal.isEmpty()) && (!m_doc->docGradients.contains(gradientStrokeVal)))
1357 				gradientStrokeVal.clear();
1358 			if (!(gradientStrokeVal.isEmpty()) && (m_doc->docGradients.contains(gradientStrokeVal)))
1359 				painter->m_strokeGradient = VGradientEx(m_doc->docGradients[gradientStrokeVal], *m_doc);
1360 			if (painter->m_strokeGradient.stops() < 2) // fall back to solid stroking if there are not enough colorstops in the gradient.
1361 			{
1362 				if (item->lineColor() != CommonStrings::None)
1363 				{
1364 					ScColorShade strokeColor(m_doc->PageColors[item->lineColor()], item->lineShade());
1365 					painter->setBrush(strokeColor);
1366 					painter->setStrokeMode(ScPainterExBase::Solid);
1367 				}
1368 				else
1369 					painter->setStrokeMode(ScPainterExBase::None);
1370 			}
1371 			else
1372 			{
1373 				FPoint fpStart(item->GrStrokeStartX, item->GrStrokeStartY);
1374 				FPoint fpEnd(item->GrStrokeEndX, item->GrStrokeEndY);
1375 				FPoint fpFocal(item->GrStrokeFocalX, item->GrStrokeFocalY);
1376 				painter->setStrokeMode(ScPainterExBase::Gradient);
1377 				painter->m_strokeGradient = VGradientEx(item->stroke_gradient, *m_doc);
1378 				if (item->GrTypeStroke == Gradient_Linear)
1379 					painter->setGradient(VGradientEx::linear, fpStart, fpEnd, fpStart, item->GrStrokeScale, item->GrStrokeSkew);
1380 				else
1381 					painter->setGradient(VGradientEx::radial, fpStart, fpEnd, fpFocal, item->GrStrokeScale, item->GrStrokeSkew);
1382 			}
1383 			painter->strokePath();
1384 		}
1385 		else if (item->lineColor() != CommonStrings::None)
1386 		{
1387 			ScColorShade scColor(m_doc->PageColors[item->lineColor()], item->lineShade());
1388 			painter->setStrokeMode(ScPainterExBase::Solid);
1389 			painter->setPen(scColor, item->lineWidth(), item->PLineArt, item->PLineEnd, item->PLineJoin);
1390 			if (item->DashValues.count() != 0)
1391 				painter->setDash(item->DashValues, item->DashOffset);
1392 			painter->strokePath();
1393 		}
1394 	}
1395 	else
1396 	{
1397 		multiLine ml = m_doc->docLineStyles[item->NamedLStyle];
1398 		for (int it = ml.size() - 1; it > -1; it--)
1399 		{
1400 			const SingleLine& sl = ml[it];
1401 			if (sl.Color != CommonStrings::None)
1402 			{
1403 				ScColorShade tmp(m_doc->PageColors[sl.Color], sl.Shade);
1404 				painter->setPen(tmp, sl.Width, static_cast<Qt::PenStyle>(sl.Dash),
1405 						static_cast<Qt::PenCapStyle>(sl.LineEnd),
1406 						static_cast<Qt::PenJoinStyle>(sl.LineJoin));
1407 				painter->strokePath();
1408 			}
1409 		}
1410 	}
1411 	if (startArrowIndex != 0)
1412 	{
1413 		FPoint Start = item->PoLine.point(0);
1414 		for (int xx = 1; xx < item->PoLine.size(); xx += 2)
1415 		{
1416 			FPoint Vector = item->PoLine.point(xx);
1417 			if ((Start.x() != Vector.x()) || (Start.y() != Vector.y()))
1418 			{
1419 				double r = atan2(Start.y() - Vector.y(), Start.x() - Vector.x()) * (180.0 / M_PI);
1420 				QTransform arrowTrans;
1421 				arrowTrans.translate(Start.x(), Start.y());
1422 				arrowTrans.rotate(r);
1423 				drawArrow(painter, item, arrowTrans, startArrowIndex);
1424 				break;
1425 			}
1426 		}
1427 	}
1428 	if (endArrowIndex != 0)
1429 	{
1430 		FPoint End = item->PoLine.point(item->PoLine.size()-2);
1431 		for (uint xx = item->PoLine.size() - 1; xx > 0; xx -= 2)
1432 		{
1433 			FPoint Vector = item->PoLine.point(xx);
1434 			if ((End.x() != Vector.x()) || (End.y() != Vector.y()))
1435 			{
1436 				double r = atan2(End.y() - Vector.y(), End.x() - Vector.x()) * (180.0 / M_PI);
1437 				QTransform arrowTrans;
1438 				arrowTrans.translate(End.x(), End.y());
1439 				arrowTrans.rotate(r);
1440 				drawArrow(painter, item, arrowTrans, endArrowIndex);
1441 				break;
1442 			}
1443 		}
1444 	}
1445 }
1446 
drawItem_Table(PageItem_Table * item,ScPainterExBase * painter,QRect clip)1447 void ScPageOutput::drawItem_Table(PageItem_Table* item, ScPainterExBase* painter, QRect clip)
1448 {
1449 	painter->save();
1450 
1451 	// Set the clip path.
1452 	painter->setupPolygon(&item->PoLine);
1453 	painter->setClipPath();
1454 
1455 	// Paint the table.
1456 	CollapsedTablePainterEx tablePainter(this, item);
1457 	tablePainter.paintTable(painter);
1458 
1459 	painter->restore();
1460 }
1461 
drawItem_Text(PageItem * item,ScPainterExBase * painter,QRect cullingArea)1462 void ScPageOutput::drawItem_Text(PageItem* item, ScPainterExBase* painter, QRect cullingArea)
1463 {
1464 	if (item->pathTextShowFrame())
1465 	{
1466 		painter->setupPolygon(&item->PoLine, false);
1467 		if (item->NamedLStyle.isEmpty())
1468 		{
1469 			if (item->lineColor() != CommonStrings::None)
1470 				painter->strokePath();
1471 		}
1472 		else
1473 		{
1474 			multiLine ml = m_doc->docLineStyles[item->NamedLStyle];
1475 			for (int it = ml.size() - 1; it > -1; it--)
1476 			{
1477 				const SingleLine& sl = ml[it];
1478 				if ((sl.Color != CommonStrings::None) && (sl.Width != 0))
1479 				{
1480 					ScColorShade tmp(m_doc->PageColors[sl.Color], sl.Shade);
1481 					painter->setPen(tmp, sl.Width,  static_cast<Qt::PenStyle>(sl.Dash),
1482 							 static_cast<Qt::PenCapStyle>(sl.LineEnd),
1483 							 static_cast<Qt::PenJoinStyle>(sl.LineJoin));
1484 					painter->drawLine(FPoint(0, 0), FPoint(item->width(), 0));
1485 				}
1486 			}
1487 		}
1488 	}
1489 	painter->save();
1490 
1491 	if ((item->fillColor() != CommonStrings::None) || (item->GrType != 0))
1492 	{
1493 		painter->setupPolygon(&item->PoLine);
1494 		fillPath(item, painter, cullingArea);
1495 	}
1496 	if ((item->isAnnotation()) && (item->annotation().Type() == Annotation::Button) && (!item->Pfile.isEmpty()) && (item->imageIsAvailable) && (item->imageVisible()) && (item->annotation().UseIcons()))
1497 	{
1498 		painter->save();
1499 		painter->setupPolygon(&item->PoLine);
1500 		painter->setClipPath();
1501 		painter->scale(item->imageXScale(), item->imageYScale());
1502 		painter->translate(static_cast<int>(item->imageXOffset() * item->imageXScale()), static_cast<int>(item->imageYOffset()  * item->imageYScale()));
1503 		if (!item->pixm.qImage().isNull())
1504 			painter->drawImage(&item->pixm, ScPainterExBase::rgbImages);
1505 		painter->restore();
1506 	}
1507 
1508 	if (item->isMasterItem())
1509 	{
1510 		// relayout necessary to get page number ok
1511 		item->invalidateLayout();
1512 		item->layout();
1513 	}
1514 
1515 	ScPageOutputPainter p(item, painter, this);
1516 	item->textLayout.renderBackground(&p);
1517 	item->textLayout.render(&p);
1518 
1519 	painter->restore();
1520 }
1521 
drawArrow(ScPainterExBase * painter,PageItem * item,QTransform & arrowTrans,int arrowIndex)1522 void ScPageOutput::drawArrow(ScPainterExBase* painter, PageItem* item, QTransform &arrowTrans, int arrowIndex)
1523 {
1524 	FPointArray arrow = m_doc->arrowStyles().at(arrowIndex - 1).points.copy();
1525 	if (item->NamedLStyle.isEmpty())
1526 	{
1527 		if (item->lineWidth() != 0.0)
1528 			arrowTrans.scale(item->lineWidth(), item->lineWidth());
1529 	}
1530 	else
1531 	{
1532 		multiLine ml = m_doc->docLineStyles[item->NamedLStyle];
1533 		if (ml[ml.size() - 1].Width != 0.0)
1534 			arrowTrans.scale(ml[ml.size() - 1].Width, ml[ml.size() - 1].Width);
1535 	}
1536 	arrow.map(arrowTrans);
1537 	painter->setupPolygon(&arrow);
1538 	if (item->NamedLStyle.isEmpty())
1539 	{
1540 		if (item->lineColor() != CommonStrings::None)
1541 		{
1542 			ScColorShade tmp(m_doc->PageColors[item->lineColor()], item->lineShade());
1543 			painter->setBrush(tmp);
1544 			painter->setBrushOpacity(1.0 - item->lineTransparency());
1545 			painter->setLineWidth(0);
1546 			painter->setFillMode(ScPainterExBase::Solid);
1547 			painter->fillPath();
1548 		}
1549 	}
1550 	else
1551 	{
1552 		multiLine ml = m_doc->docLineStyles[item->NamedLStyle];
1553 		if (ml[0].Color != CommonStrings::None)
1554 		{
1555 			ScColorShade tmp(m_doc->PageColors[ml[0].Color], ml[0].Shade);
1556 			painter->setBrush(tmp);
1557 			painter->setLineWidth(0);
1558 			painter->setFillMode(ScPainterExBase::Solid);
1559 			painter->fillPath();
1560 		}
1561 		for (int it = ml.size() - 1; it > 0; it--)
1562 		{
1563 			if (ml[it].Color != CommonStrings::None)
1564 			{
1565 				ScColorShade tmp(m_doc->PageColors[ml[it].Color], ml[it].Shade);
1566 				painter->setPen(tmp, ml[it].Width, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin);
1567 				painter->strokePath();
1568 			}
1569 		}
1570 	}
1571 }
1572 
drawMarks(ScPage * page,ScPainterExBase * painter,const MarksOptions & options)1573 void ScPageOutput::drawMarks(ScPage* page, ScPainterExBase* painter, const MarksOptions& options)
1574 {
1575 	double markLength = options.markLength;
1576 	double markOffs   = options.markOffset;
1577 	double bleedLeft = 0.0, bleedRight = 0.0;
1578 	double bleedBottom = options.BleedBottom;
1579 	double bleedTop = options.BleedTop;
1580 	if (!options.cropMarks && !options.bleedMarks && !options.registrationMarks && !options.colorMarks)
1581 		return;
1582 	if (m_doc->locationOfPage(page->pageNr()) == LeftPage)
1583 	{
1584 		bleedRight = options.BleedRight;
1585 		bleedLeft  = options.BleedLeft;
1586 	}
1587 	else if (m_doc->locationOfPage(page->pageNr()) == RightPage)
1588 	{
1589 		bleedRight = options.BleedLeft;
1590 		bleedLeft  = options.BleedRight;
1591 	}
1592 	else
1593 	{
1594 		bleedRight = options.BleedLeft;
1595 		bleedLeft  = options.BleedLeft;
1596 	}
1597 	double width = page->width();
1598 	double height = page->height();
1599 	double offsetX = page->xOffset();
1600 	double offsetY = page->yOffset();
1601 	QPointF bleedTopLeft(offsetX - bleedLeft, offsetY - bleedTop);
1602 	QPointF bleedBottomRight(offsetX + width + bleedRight, offsetY + height + bleedBottom);
1603 	QRectF  bleedBox(bleedTopLeft, bleedBottomRight);
1604 	painter->save();
1605 	painter->setLineWidth(0.5);
1606 	painter->setPen(ScColorShade(Qt::black, 100), 0.5, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin);
1607 	if (options.cropMarks)
1608 	{
1609 		FPoint start, end;
1610 		double left = offsetX, right = offsetX + width;
1611 		double bottom = offsetY + height, top = offsetY;
1612 		drawBoxMarks(painter, QRectF(QPointF(left, top), QPointF(right, bottom)), bleedBox, markOffs, markLength);
1613 	}
1614 	if (options.bleedMarks)
1615 	{
1616 		FPoint start, end;
1617 		double left = offsetX - bleedLeft, right = offsetX + width + bleedRight;
1618 		double bottom = offsetY + height + bleedBottom, top = offsetY - bleedTop;
1619 		drawBoxMarks(painter, QRectF(QPointF(left, top), QPointF(right, bottom)), bleedBox, markOffs, markLength);
1620 	}
1621 	if (options.registrationMarks)
1622 	{
1623 		double posX = (2* offsetX + width) / 2.0 - 7.0;
1624 		double posY = (offsetY + height + bleedBottom + markOffs + 3.0);
1625 		painter->save();
1626 		painter->translate(posX, posY);
1627 		drawRegistrationCross(painter);
1628 		painter->restore();
1629 		posX = (2 * offsetX + width) / 2.0 - 7.0;
1630 		posY = (offsetY - bleedTop - markOffs - 17);
1631 		painter->save();
1632 		painter->translate(posX, posY);
1633 		drawRegistrationCross(painter);
1634 		painter->restore();
1635 
1636 		posX = (offsetX - bleedLeft - markOffs - 17);
1637 		posY = (2 * offsetY + height) / 2.0 - 7.0;
1638 		painter->save();
1639 		painter->translate(posX, posY);
1640 		drawRegistrationCross(painter);
1641 		painter->restore();
1642 		posX = (offsetX + width + bleedRight + markOffs + 3.0);
1643 		posY = (2 * offsetY + height) / 2.0 - 7.0;
1644 		painter->save();
1645 		painter->translate(posX, posY);
1646 		drawRegistrationCross(painter);
1647 		painter->restore();
1648 	}
1649 	if (options.colorMarks)
1650 	{
1651 		int shade = 100;
1652 		double startX = offsetX + 6.0;
1653 		double startY = offsetY - bleedTop - markOffs - 16.0;
1654 		ScColorShade strokecolor(ScColor(0, 0, 0, 255), 100);
1655 		painter->setPen(strokecolor, 0.5, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin);
1656 		painter->setFillMode(ScPainterExBase::Solid);
1657 		for (int i = 0; i < 11; i++)
1658 		{
1659 			ScColorShade fillcolor(ScColor(0, 0, 0, 255), shade);
1660 			painter->setBrush(fillcolor);
1661 			painter->drawRect(startX + i * 14, startY, 14, 14);
1662 			shade -= 10;
1663 		}
1664 		startX = offsetX + width - 20.0;
1665 		painter->setBrush(ScColorShade(ScColor(0, 0, 0, 255), 50));
1666 		painter->drawRect(startX, startY, 14, 14);
1667 		startX -= 14;
1668 		painter->setBrush(ScColorShade(ScColor(0, 0, 255, 0), 50));
1669 		painter->drawRect(startX, startY, 14, 14);
1670 		startX -= 14;
1671 		painter->setBrush(ScColorShade(ScColor(0, 255, 0, 0), 50));
1672 		painter->drawRect(startX, startY, 14, 14);
1673 		startX -= 14;
1674 		painter->setBrush(ScColorShade(ScColor(255, 0, 0, 0), 50));
1675 		painter->drawRect(startX, startY, 14, 14);
1676 		startX -= 14;
1677 		painter->setBrush(ScColorShade(ScColor(255, 255, 0, 0), 100));
1678 		painter->drawRect(startX, startY, 14, 14);
1679 		startX -= 14;
1680 		painter->setBrush(ScColorShade(ScColor(255, 0, 255, 0), 100));
1681 		painter->drawRect(startX, startY, 14, 14);
1682 		startX -= 14;
1683 		painter->setBrush(ScColorShade(ScColor(0, 255, 255, 0), 100));
1684 		painter->drawRect(startX, startY, 14, 14);
1685 		startX -= 14;
1686 		painter->setBrush(ScColorShade(ScColor(0, 0, 0, 255), 100));
1687 		painter->drawRect(startX, startY, 14, 14);
1688 		startX -= 14;
1689 		painter->setBrush(ScColorShade(ScColor(0, 0, 255, 0), 100));
1690 		painter->drawRect(startX, startY, 14, 14);
1691 		startX -= 14;
1692 		painter->setBrush(ScColorShade(ScColor(0, 255, 0, 0), 100));
1693 		painter->drawRect(startX, startY, 14, 14);
1694 		startX -= 14;
1695 		painter->setBrush(ScColorShade(ScColor(255, 0, 0, 0), 100));
1696 		painter->drawRect(startX, startY, 14, 14);
1697 	}
1698 	painter->restore();
1699 }
1700 
drawBoxMarks(ScPainterExBase * painter,const QRectF & box,const QRectF & bleedBox,double offset,double markSize)1701 void ScPageOutput::drawBoxMarks(ScPainterExBase* painter, const QRectF& box, const QRectF& bleedBox, double offset , double markSize)
1702 {
1703 	FPoint start, end;
1704 	double left   = box.left(), right = box.right();
1705 	double bottom = box.bottom(), top = box.top();
1706 	double bleedLeft = bleedBox.left(), bleedRight = bleedBox.right();
1707 	double bleedBottom = bleedBox.bottom(), bleedTop = bleedBox.top();
1708 	// Top Left
1709 	start.setXY(bleedLeft - offset, top);
1710 	end.setXY  (bleedLeft - offset - markSize, top);
1711 	painter->drawLine(start, end);
1712 	start.setXY(left, bleedTop - offset);
1713 	end.setXY  (left, bleedTop - offset - markSize);
1714 	painter->drawLine(start, end);
1715 	// Top Right
1716 	start.setXY(bleedRight + offset, top);
1717 	end.setXY  (bleedRight + offset + markSize, top);
1718 	painter->drawLine(start, end);
1719 	start.setXY(right, bleedTop - offset);
1720 	end.setXY  (right, bleedTop - offset - markSize);
1721 	painter->drawLine(start, end);
1722 	// Bottom Left
1723 	start.setXY(bleedLeft - offset, bottom);
1724 	end.setXY  (bleedLeft - offset - markSize, bottom);
1725 	painter->drawLine(start, end);
1726 	start.setXY(left, bleedBottom + offset);
1727 	end.setXY  (left, bleedBottom + offset + markSize);
1728 	painter->drawLine(start, end);
1729 	// Bottom Right
1730 	start.setXY(bleedRight + offset, bottom);
1731 	end.setXY  (bleedRight + offset + markSize, bottom);
1732 	painter->drawLine(start, end);
1733 	start.setXY(right, bleedBottom + offset);
1734 	end.setXY  (right, bleedBottom + offset + markSize);
1735 	painter->drawLine(start, end);
1736 }
1737 
drawRegistrationCross(ScPainterExBase * painter)1738 void ScPageOutput::drawRegistrationCross(ScPainterExBase* painter)
1739 {
1740 	painter->save();
1741 
1742 	painter->newPath();
1743 	painter->moveTo(0.0, 7.0);
1744 	painter->lineTo(14.0, 7.0);
1745 	painter->strokePath();
1746 
1747 	painter->newPath();
1748 	painter->moveTo(7.0, 0.0);
1749 	painter->lineTo(7.0, 14.0);
1750 	painter->strokePath();
1751 
1752 	painter->newPath();
1753 	painter->moveTo(13.0, 7.0);
1754 	painter->curveTo(FPoint(13.0, 10.31383), FPoint(10.31383, 13.0), FPoint(7.0, 13.0));
1755 	painter->curveTo(FPoint(3.68629, 13.0) , FPoint(1.0, 10.31383) , FPoint(1.0, 7.0));
1756 	painter->curveTo(FPoint(1.0, 3.68629)  , FPoint(3.68629, 1.0) , FPoint(7.0, 1.0));
1757 	painter->curveTo(FPoint(10.31383, 1.0) , FPoint(13.0, 3.68629) , FPoint(13.0, 7.0));
1758 	painter->strokePath();
1759 
1760 	painter->newPath();
1761 	painter->moveTo(10.5, 7.0);
1762 	painter->curveTo(FPoint(10.5, 8.93307), FPoint(8.93307, 10.5), FPoint(7.0, 10.5));
1763 	painter->curveTo(FPoint(5.067, 10.5)  , FPoint(3.5, 8.93307) , FPoint(3.5, 7.0));
1764 	painter->curveTo(FPoint(3.5, 5.067)   , FPoint(5.067, 3.5)   , FPoint(7.0, 3.5));
1765 	painter->curveTo(FPoint(8.93307, 3.5) , FPoint(10.5, 5.067)  , FPoint(10.5, 7.0));
1766 	painter->strokePath();
1767 
1768 	painter->restore();
1769 }
1770 
fillPath(PageItem * item,ScPainterExBase * painter,QRect clip)1771 void ScPageOutput::fillPath(PageItem* item, ScPainterExBase* painter, QRect clip)
1772 {
1773 	if (painter->fillMode() == ScPainterExBase::Pattern && !painter->hasCapability(ScPainterExBase::patterns))
1774 		drawPattern(item, painter, clip);
1775 	else
1776 		painter->fillPath();
1777 }
1778 
strokePath(PageItem * item,ScPainterExBase * painter,QRect clip)1779 void ScPageOutput::strokePath(PageItem* item, ScPainterExBase* painter, QRect clip)
1780 {
1781 	painter->strokePath();
1782 }
1783