Rev 24116 |
Blame |
Compare with Previous |
Last modification |
View Log
| RSS feed
/*
For general Scribus (>=1.3.2) copyright and licensing information please refer
to the COPYING file provided with the program. Following this notice may exist
a copyright and/or license notice that predates the release of Scribus 1.3.2
for which a new license (GPL+exception) is in place.
*/
#include "scpageoutput.h"
#include <QList>
#include <QPointF>
#include <QRectF>
#include <QStack>
#include <pageitem_textframe.h>
#include "cmsettings.h"
#include "collapsedtablepainterex.h"
#include "commonstrings.h"
#include "pageitem.h"
#include "pageitem_arc.h"
#include "pageitem_group.h"
#include "pageitem_imageframe.h"
#include "pageitem_line.h"
#include "pageitem_polygon.h"
#include "pageitem_polyline.h"
#include "pageitem_regularpolygon.h"
#include "pageitem_spiral.h"
#include "pageitem_table.h"
#include "prefsmanager.h"
#include "scfonts.h"
#include "scimage.h"
#include "scpage.h"
#include "scpattern.h"
#include "text/textlayoutpainter.h"
#include "scribusdoc.h"
#include "util.h"
#include "util_formats.h"
#include "util_math.h"
#include "text/boxes.h"
MarksOptions::MarksOptions()
{
markLength = 20.0;
markOffset = 0.0;
BleedTop = 0.0;
BleedLeft = 0.0;
BleedRight = 0.0;
BleedBottom = 0.0;
cropMarks = false;
bleedMarks = false;
registrationMarks = false;
colorMarks = false;
docInfoMarks = false;
}
MarksOptions::MarksOptions(struct PrintOptions& opt)
{
markLength = opt.markLength;
markOffset = opt.markOffset;
BleedTop = opt.bleeds.top();
BleedLeft = opt.bleeds.left();
BleedRight = opt.bleeds.right();
BleedBottom = opt.bleeds.bottom();
cropMarks = opt.cropMarks;
bleedMarks = opt.bleedMarks;
registrationMarks = opt.registrationMarks;
colorMarks = opt.colorMarks;
docInfoMarks = true;
}
ScPageOutput::ScPageOutput(ScribusDoc* doc, bool reloadImages, int resolution, bool useProfiles)
: m_marksOptions()
{
m_doc = doc;
m_reloadImages = reloadImages;
m_imageRes = resolution;
m_useProfiles = useProfiles;
}
ScImage::RequestType ScPageOutput::translateImageModeToRequest(ScPainterExBase::ImageMode mode)
{
ScImage::RequestType value = ScImage::RGBData;
if (mode == ScPainterExBase::cmykImages)
value = ScImage::CMYKData;
else if (mode == ScPainterExBase::rgbImages)
value = ScImage::RGBData;
else if (mode == ScPainterExBase::rawImages)
value = ScImage::RawData;
return value;
}
void ScPageOutput::drawPage(ScPage* page, ScPainterExBase* painter)
{
int clipx = static_cast<int>(page->xOffset());
int clipy = static_cast<int>(page->yOffset());
int clipw = qRound(page->width());
int cliph = qRound(page->height());
ScLayer layer;
layer.isViewable = false;
uint layerCount = m_doc->layerCount();
for (uint la = 0; la < layerCount; ++la)
{
m_doc->Layers.levelToLayer(layer, la);
drawMasterItems(painter, page, layer, QRect(clipx, clipy, clipw, cliph));
drawPageItems(painter, page, layer, QRect(clipx, clipy, clipw, cliph));
}
drawMarks(page, painter, m_marksOptions);
}
void ScPageOutput::drawMasterItems(ScPainterExBase *painter, ScPage *page, ScLayer& layer, QRect clip)
{
PageItem* currItem;
if (page->masterPageNameEmpty())
return;
if (page->FromMaster.count() <= 0)
return;
if (!layer.isViewable || !layer.isPrintable)
return;
ScPage* Mp = m_doc->MasterPages.at(m_doc->MasterNames[page->masterPageName()]);
int pageFromMasterCount = page->FromMaster.count();
for (int i = 0; i < pageFromMasterCount; ++i)
{
currItem = page->FromMaster.at(i);
if (currItem->m_layerID != layer.ID)
continue;
if ((currItem->OwnPage != -1) && (currItem->OwnPage != static_cast<int>(Mp->pageNr())))
continue;
if (!currItem->printEnabled())
continue;
int savedOwnPage = currItem->OwnPage;
double OldX = currItem->xPos();
double OldY = currItem->yPos();
double OldBX = currItem->BoundingX;
double OldBY = currItem->BoundingY;
currItem->OwnPage = page->pageNr();
if (!currItem->ChangedMasterItem)
{
currItem->moveBy(-Mp->xOffset() + page->xOffset(), -Mp->yOffset() + page->yOffset(), true);
currItem->BoundingX = OldBX - Mp->xOffset() + page->xOffset();
currItem->BoundingY = OldBY - Mp->yOffset() + page->yOffset();
}
QRectF oldR(currItem->getBoundingRect().adjusted(0.0, 0.0, 1.0, 1.0));
if (clip.intersects(oldR.toRect()))
drawItem(currItem, painter, clip);
currItem->OwnPage = savedOwnPage;
if (!currItem->ChangedMasterItem)
{
currItem->setXYPos(OldX, OldY, true);
currItem->BoundingX = OldBX;
currItem->BoundingY = OldBY;
}
}
}
void ScPageOutput::drawPageItems(ScPainterExBase *painter, ScPage *page, ScLayer& layer, QRect clip)
{
PageItem *currItem;
if (m_doc->Items->count() <= 0)
return;
if (!layer.isViewable || !layer.isPrintable)
return;
int docCurrPageNo = static_cast<int>(page->pageNr());
for (int it = 0; it < m_doc->Items->count(); ++it)
{
currItem = m_doc->Items->at(it);
if (currItem->m_layerID != layer.ID)
continue;
if (!currItem->printEnabled())
continue;
if ((m_doc->masterPageMode()) && ((currItem->OwnPage != -1) && (currItem->OwnPage != docCurrPageNo)))
continue;
if (!m_doc->masterPageMode() && !currItem->OnMasterPage.isEmpty())
{
if (currItem->OnMasterPage != page->pageName())
continue;
}
QRectF oldR(currItem->getBoundingRect().adjusted(0.0, 0.0, 1.0, 1.0));
if (clip.intersects(oldR.toRect()))
{
drawItem(currItem, painter, clip);
}
}
}
void ScPageOutput::drawItem(PageItem* item, ScPainterExBase* painter, QRect clip)
{
if (clip.isNull())
{
clip = QRectF(QPointF(m_doc->minCanvasCoordinate.x(), m_doc->minCanvasCoordinate.y()),
QPointF(m_doc->maxCanvasCoordinate.x(), m_doc->maxCanvasCoordinate.y())).toAlignedRect();
}
drawItem_Pre(item, painter);
PageItem::ItemType itemType = item->itemType();
if (itemType == PageItem::Arc)
drawItem_Arc((PageItem_Arc*) item, painter, clip);
else if (itemType == PageItem::Group)
drawItem_Group((PageItem_Group*) item, painter, clip);
else if (itemType == PageItem::ImageFrame)
drawItem_ImageFrame((PageItem_ImageFrame*) item, painter, clip);
else if (itemType == PageItem::Line)
drawItem_Line((PageItem_Line*) item, painter, clip);
else if (itemType == PageItem::Polygon)
drawItem_Polygon((PageItem_Polygon*) item, painter, clip);
else if (itemType == PageItem::PolyLine)
drawItem_PolyLine((PageItem_PolyLine*) item, painter, clip);
else if (itemType == PageItem::RegularPolygon)
drawItem_RegularPolygon((PageItem_RegularPolygon*) item, painter, clip);
else if (itemType == PageItem::Spiral)
drawItem_Spiral((PageItem_Spiral*) item, painter, clip);
else if (itemType == PageItem::Table)
drawItem_Table((PageItem_Table*) item, painter, clip);
else if (itemType == PageItem::TextFrame || itemType == PageItem::PathText)
drawItem_Text(item, painter, clip);
drawItem_Post(item, painter);
}
void ScPageOutput::drawItem_Pre(PageItem* item, ScPainterExBase* painter)
{
painter->save();
if (!item->isEmbedded)
painter->translate(item->xPos(), item->yPos());
painter->rotate(item->rotation());
painter->setBlendModeFill(item->fillBlendmode());
painter->setLineWidth(item->lineWidth());
if (item->isGroup())
return;
if (item->GrType == Gradient_Pattern)
{
QString pat = item->pattern();
ScPattern *pattern = m_doc->checkedPattern(pat);
if (!pattern)
{
painter->m_fillGradient = VGradientEx(VGradientEx::linear);
if (item->fillColor() != CommonStrings::None)
{
painter->setBrush(ScColorShade(m_doc->PageColors[item->fillColor()], (int) item->fillShade()));
painter->setFillMode(ScPainterExBase::Solid);
}
else
painter->setFillMode(ScPainterExBase::None);
}
else
{
QTransform patternTransform;
double patternScaleX, patternScaleY, patternOffsetX, patternOffsetY, patternRotation, patternSkewX, patternSkewY;
bool patternMirrorX, patternMirrorY;
item->patternTransform(patternScaleX, patternScaleY, patternOffsetX, patternOffsetY, patternRotation, patternSkewX, patternSkewY);
item->patternFlip(patternMirrorX, patternMirrorY);
painter->setPattern(pattern, patternScaleX, patternScaleY, patternOffsetX, patternOffsetY, patternRotation, patternSkewX, patternSkewY, patternMirrorX, patternMirrorY);
painter->setFillMode(ScPainterExBase::Pattern);
}
}
else if (item->GrType == Gradient_4Colors)
{
painter->setFillMode(ScPainterExBase::Gradient);
FPoint pG1 = FPoint(0, 0);
FPoint pG2 = FPoint(item->width(), 0);
FPoint pG3 = FPoint(item->width(), item->height());
FPoint pG4 = FPoint(0, item->height());
ScColorShade col1(m_doc->PageColors[item->GrColorP1], item->GrCol1Shade);
ScColorShade col2(m_doc->PageColors[item->GrColorP2], item->GrCol2Shade);
ScColorShade col3(m_doc->PageColors[item->GrColorP3], item->GrCol3Shade);
ScColorShade col4(m_doc->PageColors[item->GrColorP4], item->GrCol4Shade);
painter->set4ColorGeometry(pG1, pG2, pG3, pG4, item->GrControl1, item->GrControl2, item->GrControl3, item->GrControl4);
painter->set4ColorColors(col1, col2, col3, col4);
}
else if (item->GrType != 0)
{
QString gradientVal = item->gradient();
if ((!gradientVal.isEmpty()) && (!m_doc->docGradients.contains(gradientVal)))
gradientVal = "";
if (!(gradientVal.isEmpty()) && (m_doc->docGradients.contains(gradientVal)))
painter->m_fillGradient = VGradientEx(m_doc->docGradients[gradientVal], *m_doc);
if ((painter->m_fillGradient.stops() < 2) && (item->GrType < Gradient_4Colors)) // fall back to solid filling if there are not enough colorstops in the gradient.
{
if (item->fillColor() != CommonStrings::None)
{
painter->setBrush(ScColorShade(m_doc->PageColors[item->fillColor()], (int) item->fillShade()));
painter->setFillMode(ScPainterExBase::Solid);
}
else
painter->setFillMode(ScPainterExBase::None);
}
else
{
FPoint fpStart(item->GrStartX, item->GrStartY), fpEnd(item->GrEndX, item->GrEndY);
FPoint fpFocal(item->GrFocalX, item->GrFocalY);
painter->setFillMode(ScPainterExBase::Gradient);
painter->m_fillGradient = VGradientEx(item->fill_gradient, *m_doc);
switch (item->GrType)
{
case 1:
case 2:
case 3:
case 4:
case 6:
painter->setGradient(VGradientEx::linear, fpStart, fpEnd, fpStart, item->GrScale, item->GrSkew);
break;
case 5:
case 7:
painter->setGradient(VGradientEx::radial, fpStart, fpEnd, fpFocal, item->GrScale, item->GrSkew);
break;
case 10:
painter->setFillMode(ScPainterExBase::Gradient);
painter->setDiamondGeometry(FPoint(0, 0), FPoint(item->width(), 0), FPoint(item->width(), item->height()), FPoint(0, item->height()),
item->GrControl1, item->GrControl2, item->GrControl3, item->GrControl4, item->GrControl5);
break;
case 11:
case 13:
painter->setFillMode(ScPainterExBase::Gradient);
painter->setMeshGradient(FPoint(0, 0), FPoint(item->width(), 0), FPoint(item->width(), item->height()), FPoint(0, item->height()), item->meshGradientArray);
break;
case 12:
painter->setFillMode(ScPainterExBase::Gradient);
painter->setMeshGradient(FPoint(0, 0), FPoint(item->width(), 0), FPoint(item->width(), item->height()), FPoint(0, item->height()), item->meshGradientPatches);
break;
}
}
}
else
{
painter->m_fillGradient = VGradientEx(VGradientEx::linear);
if (item->fillColor() != CommonStrings::None)
{
painter->setBrush(ScColorShade(m_doc->PageColors[item->fillColor()], (int) item->fillShade()));
painter->setFillMode(ScPainterExBase::Solid);
}
else
painter->setFillMode(ScPainterExBase::None);
}
if (item->lineColor() != CommonStrings::None)
{
if ((item->lineWidth() == 0) && !item->asLine())
painter->setLineWidth(0);
else
{
ScColorShade tmp(m_doc->PageColors[item->lineColor()], (int) item->lineShade());
painter->setPen(tmp , item->lineWidth(), item->PLineArt, item->PLineEnd, item->PLineJoin);
if (item->DashValues.count() != 0)
painter->setDash(item->DashValues, item->DashOffset);
}
}
else
painter->setLineWidth(0);
painter->setBrushOpacity(1.0 - item->fillTransparency());
painter->setPenOpacity(1.0 - item->lineTransparency());
painter->setFillRule(item->fillRule);
if ((item->GrMask == GradMask_Linear) || (item->GrMask == GradMask_Radial) || (item->GrMask == GradMask_LinearLumAlpha) || (item->GrMask == GradMask_RadialLumAlpha))
{
QString gradientMaskVal = item->gradientMaskVal;
FPoint fpMaskStart(item->GrMaskStartX, item->GrMaskStartY);
FPoint fpMaskEnd(item->GrMaskEndX, item->GrMaskEndY);
FPoint fpMaskFocal(item->GrMaskFocalX, item->GrMaskFocalY);
if ((item->GrMask == GradMask_Linear) || (item->GrMask == GradMask_Radial))
painter->setMaskMode(1);
else
painter->setMaskMode(3);
if ((!gradientMaskVal.isEmpty()) && (!m_doc->docGradients.contains(gradientMaskVal)))
gradientMaskVal = "";
if (!(gradientMaskVal.isEmpty()) && (m_doc->docGradients.contains(gradientMaskVal)))
painter->m_maskGradient = VGradientEx(m_doc->docGradients[gradientMaskVal], *m_doc);
if ((item->GrMask == GradMask_Linear) || (item->GrMask == GradMask_LinearLumAlpha))
painter->setGradientMask(VGradientEx::linear, fpMaskStart, fpMaskEnd, fpMaskStart, item->GrMaskScale, item->GrMaskSkew);
else
painter->setGradientMask(VGradientEx::radial, fpMaskStart, fpMaskEnd, fpMaskFocal, item->GrMaskScale, item->GrMaskSkew);
}
else if ((item->GrMask == GradMask_Pattern) || (item->GrMask == GradMask_PatternLumAlpha) || (item->GrMask == GradMask_PatternLumAlphaInverted) || (item->GrMask == GradMask_PatternInverted))
{
QString patternMaskVal = item->patternMaskVal;
ScPattern *patternMask = m_doc->checkedPattern(patternMaskVal);
if (patternMask)
{
painter->setPatternMask(patternMask, item->patternMaskScaleX, item->patternMaskScaleY, item->patternMaskOffsetX, item->patternMaskOffsetY,
item->patternMaskRotation, item->patternMaskSkewX, item->patternMaskSkewY, item->patternMaskMirrorX, item->patternMaskMirrorY);
if (item->GrMask == GradMask_Pattern)
painter->setMaskMode(2);
else if (item->GrMask == GradMask_PatternLumAlpha)
painter->setMaskMode(4);
else if (item->GrMask == GradMask_PatternLumAlphaInverted)
painter->setMaskMode(5);
else
painter->setMaskMode(6);
}
else
{
painter->setMaskMode(0);
}
}
else
painter->setMaskMode(0);
}
void ScPageOutput::drawItem_Post(PageItem* item, ScPainterExBase* painter)
{
bool doStroke = true;
if (!item->isGroup())
{
painter->setMaskMode(0);
if (item->isGroup() || item->isLine() || item->isPathText() || item->isPolyLine() || item->isSpiral() || item->isSymbol() || item->isTable())
doStroke = false;
if (doStroke)
{
painter->setBlendModeStroke(item->lineBlendmode());
painter->setPenOpacity(1.0 - item->lineTransparency());
if ((item->lineColor() != CommonStrings::None)|| (!item->strokePattern().isEmpty()) || (item->strokeGradientType() > 0))
{
ScColorShade tmp(m_doc->PageColors[item->lineColor()], (int) item->lineShade());
painter->setPen(tmp, item->lineWidth(), item->PLineArt, item->PLineEnd, item->PLineJoin);
if (item->DashValues.count() != 0)
painter->setDash(item->DashValues, item->DashOffset);
}
else
painter->setLineWidth(0);
if ((item->itemType() == PageItem::LatexFrame) || (item->itemType() == PageItem::ImageFrame) || (item->itemType() == PageItem::TextFrame) || (item->itemType() == PageItem::OSGFrame))
painter->setupPolygon(&item->PoLine);
if (item->NamedLStyle.isEmpty())
{
QString patternStrokeVal = item->strokePattern();
ScPattern *strokePattern = m_doc->checkedPattern(patternStrokeVal);
if (strokePattern)
{
if (item->patternStrokePath)
{
QPainterPath guidePath = item->PoLine.toQPainterPath(false);
drawStrokePattern(item, painter, guidePath);
}
else
{
painter->setPattern(strokePattern, item->patternStrokeScaleX, item->patternStrokeScaleY, item->patternStrokeOffsetX, item->patternStrokeOffsetY, item->patternStrokeRotation, item->patternStrokeSkewX, item->patternStrokeSkewY, item->patternStrokeMirrorX, item->patternStrokeMirrorY);
painter->setStrokeMode(ScPainterExBase::Pattern);
painter->strokePath();
}
}
else if (item->strokeGradientType() > 0)
{
QString gradientStrokeVal = item->strokeGradient();
if ((!gradientStrokeVal.isEmpty()) && (!m_doc->docGradients.contains(gradientStrokeVal)))
gradientStrokeVal.clear();
if (!(gradientStrokeVal.isEmpty()) && (m_doc->docGradients.contains(gradientStrokeVal)))
painter->m_strokeGradient = VGradientEx(m_doc->docGradients[gradientStrokeVal], *m_doc);
if (painter->m_strokeGradient.stops() < 2) // fall back to solid stroking if there are not enough colorstops in the gradient.
{
if (item->lineColor() != CommonStrings::None)
{
ScColorShade strokeColor(m_doc->PageColors[item->lineColor()], item->lineShade());
painter->setBrush(strokeColor);
painter->setStrokeMode(ScPainterExBase::Solid);
}
else
painter->setStrokeMode(ScPainterExBase::None);
}
else
{
FPoint fpStart(item->GrStrokeStartX, item->GrStrokeStartY);
FPoint fpEnd(item->GrStrokeEndX, item->GrStrokeEndY);
FPoint fpFocal(item->GrStrokeFocalX, item->GrStrokeFocalY);
painter->setStrokeMode(ScPainterExBase::Gradient);
painter->m_strokeGradient = VGradientEx(item->stroke_gradient, *m_doc);
if (item->GrTypeStroke == Gradient_Linear)
painter->setGradient(VGradientEx::linear, fpStart, fpEnd, fpStart, item->GrStrokeScale, item->GrStrokeSkew);
else
painter->setGradient(VGradientEx::radial, fpStart, fpEnd, fpFocal, item->GrStrokeScale, item->GrStrokeSkew);
}
painter->strokePath();
}
else if (item->lineColor() != CommonStrings::None)
{
ScColorShade scColor(m_doc->PageColors[item->lineColor()], item->lineShade());
painter->setStrokeMode(ScPainterExBase::Solid);
painter->setPen(scColor, item->lineWidth(), item->PLineArt, item->PLineEnd, item->PLineJoin);
if (item->DashValues.count() != 0)
painter->setDash(item->DashValues, item->DashOffset);
painter->strokePath();
}
}
else
{
multiLine ml = m_doc->docLineStyles[item->NamedLStyle];
for (int it = ml.size() - 1; it > -1; it--)
{
const SingleLine& sl = ml[it];
if ((sl.Color != CommonStrings::None) && (sl.Width != 0))
{
ScColorShade tmp(m_doc->PageColors[sl.Color], sl.Shade);
painter->setPen(tmp, sl.Width, static_cast<Qt::PenStyle>(sl.Dash),
static_cast<Qt::PenCapStyle>(sl.LineEnd),
static_cast<Qt::PenJoinStyle>(sl.LineJoin));
painter->strokePath();
}
}
}
painter->setBlendModeStroke(0);
}
}
painter->setFillMode(ScPainterExBase::Solid);
painter->setBlendModeFill(0);
painter->setStrokeMode(ScPainterExBase::Solid);
painter->setBlendModeStroke(0);
painter->restore();
}
void ScPageOutput::drawItem_Embedded(PageItem* item, ScPainterExBase *p, QRect clip, const CharStyle& style, PageItem* cembedded)
{
if (!cembedded)
return;
QList<PageItem*> emG;
emG.append(cembedded);
for (int em = 0; em < emG.count(); ++em)
{
PageItem* embedded = emG.at(em);
p->save();
double x = embedded->xPos();
double y = embedded->yPos();
embedded->setXPos(embedded->gXpos, true);
embedded->setYPos((embedded->gHeight * (style.scaleV() / 1000.0)) + embedded->gYpos, true);
p->translate((embedded->gXpos * (style.scaleH() / 1000.0)), ( - (embedded->gHeight * (style.scaleV() / 1000.0)) + embedded->gYpos * (style.scaleV() / 1000.0)));
if (style.baselineOffset() != 0)
{
p->translate(0, -embedded->gHeight * (style.baselineOffset() / 1000.0));
embedded->setYPos(embedded->yPos() - embedded->gHeight * (style.baselineOffset() / 1000.0));
}
p->scale(style.scaleH() / 1000.0, style.scaleV() / 1000.0);
double pws = embedded->m_lineWidth;
drawItem_Pre(embedded, p);
switch (embedded->itemType())
{
case PageItem::ImageFrame:
case PageItem::LatexFrame:
case PageItem::TextFrame:
case PageItem::Polygon:
case PageItem::PathText:
case PageItem::Symbol:
case PageItem::Group:
case PageItem::RegularPolygon:
case PageItem::Arc:
drawItem(embedded, p, clip);
break;
case PageItem::Line:
case PageItem::PolyLine:
embedded->m_lineWidth = pws * qMin(style.scaleH() / 1000.0, style.scaleV() / 1000.0);
drawItem(embedded, p, clip);
break;
default:
break;
}
embedded->m_lineWidth = pws * qMin(style.scaleH() / 1000.0, style.scaleV() / 1000.0);
drawItem_Post(embedded, p);
embedded->setXPos(x, true);
embedded->setYPos(y, true);
p->restore();
embedded->m_lineWidth = pws;
}
}
void ScPageOutput::drawPattern(PageItem* item, ScPainterExBase* painter, QRect clip)
{
double x1, x2, y1, y2;
ScPattern& pattern = m_doc->docPatterns[item->pattern()];
double patternScaleX, patternScaleY, patternOffsetX, patternOffsetY, patternRotation, patternSkewX, patternSkewY;
item->patternTransform(patternScaleX, patternScaleY, patternOffsetX, patternOffsetY, patternRotation, patternSkewX, patternSkewY);
// Compute pattern tansformation matrix and its inverse for converting pattern coordinates
// to pageitem coordinates
QTransform matrix, invMat;
matrix.translate(patternOffsetX, patternOffsetY);
matrix.rotate(patternRotation);
matrix.shear(patternSkewX, patternSkewY);
matrix.scale(pattern.scaleX, pattern.scaleY);
matrix.scale(patternScaleX / 100.0 , patternScaleY / 100.0);
invMat.scale((patternScaleX != 0) ? (100 /patternScaleX) : 1.0, (patternScaleY != 0) ? (100 /patternScaleY) : 1.0);
invMat.scale((pattern.scaleX != 0) ? (1 /pattern.scaleX) : 1.0, (pattern.scaleY != 0) ? (1 /pattern.scaleY) : 1.0);
invMat.rotate(-patternRotation);
invMat.translate(-patternOffsetX, -patternOffsetY);
// Compute bounding box in which pattern item will be drawn
double width = item->width();
double height = item->height();
double rot = patternRotation - floor(patternRotation / 90) * 90;
double ctheta = cos(rot * M_PI / 180);
double stheta = sin(rot * M_PI / 180);
QRectF itemRect(0.0, 0.0, item->width(), item->height());
QPointF pa(width * stheta * stheta, -width * stheta * ctheta);
QPointF pb(width + height * ctheta * stheta, height * stheta * stheta);
QPointF pc(-height * ctheta * stheta, height * ctheta * ctheta);
QPointF pd(width * ctheta * ctheta, height + width * ctheta * stheta);
QPointF ipa = invMat.map(pa), ipb = invMat.map(pb);
QPointF ipc = invMat.map(pc), ipd = invMat.map(pd);
painter->save();
if (!item->imageClip.empty())
{
painter->setupPolygon(&item->imageClip);
painter->setClipPath();
}
painter->setupPolygon(&item->PoLine);
painter->setClipPath();
for (int index = 0; index < pattern.items.count(); index++)
{
QRectF itRect;
PageItem* it = pattern.items.at(index);
painter->save();
painter->translate(patternOffsetX, patternOffsetY);
painter->rotate(patternRotation);
painter->scale(pattern.scaleX, pattern.scaleY);
painter->scale(patternScaleX / 100.0, patternScaleY / 100.0);
double patWidth = (pattern.width != 0.0) ? pattern.width : 1.0;
double patHeight = (pattern.height != 0.0) ? pattern.height : 1.0;
double kxa = (ipa.x() - it->gXpos) / patWidth;
double kxb = (ipb.x() - it->gXpos) / patWidth;
double kxc = (ipc.x() - it->gXpos) / patWidth;
double kxd = (ipd.x() - it->gXpos) / patWidth;
double kya = (ipa.y() - it->gYpos) / patHeight;
double kyb = (ipb.y() - it->gYpos) / patHeight;
double kyc = (ipc.y() - it->gYpos) / patHeight;
double kyd = (ipd.y() - it->gYpos) / patHeight;
int kxMin = (int) floor(qMin(qMin(kxa, kxb), qMin(kxc, kxd)));
int kxMax = (int) ceil (qMax(qMax(kxa, kxb), qMax(kxc, kxd)));
int kyMin = (int) floor(qMin(qMin(kya, kyb), qMin(kyc, kyd)));
int kyMax = (int) ceil (qMax(qMax(kya, kyb), qMax(kyc, kyd)));
double itx = it->xPos();
double ity = it->yPos();
double itPosX = it->gXpos, itPosY = it->gYpos;
for (int kx = kxMin; kx <= kxMax; kx++)
{
for (int ky = kyMin; ky <= kyMax; ky++)
{
itPosX = it->gXpos + kx * pattern.width;
itPosY = it->gYpos + ky * pattern.height;
it->setXYPos(itPosX, itPosY);
it->getBoundingRect(&x1, &y1, &x2, &y2);
itRect.setCoords(x1, y1, x2, y2);
itRect = matrix.mapRect(itRect);
if (itRect.intersects(itemRect))
drawItem(it, painter, clip);
}
}
it->setXYPos(itx, ity);
painter->restore();
}
painter->restore();
}
void ScPageOutput::drawStrokePattern(PageItem* item, ScPainterExBase* painter, const QPainterPath& path)
{
}
void ScPageOutput::drawItem_Arc(PageItem_Arc* item , ScPainterExBase* painter, QRect clip)
{
painter->setupPolygon(&item->PoLine);
fillPath(item, painter, clip);
}
void ScPageOutput::drawItem_Group(PageItem_Group* item, ScPainterExBase* painter, QRect clip)
{
if (item->groupItemList.isEmpty())
return;
painter->save();
if (item->imageFlippedH())
{
painter->translate(item->width(), 0);
painter->scale(-1, 1);
}
if (item->imageFlippedV())
{
painter->translate(0, item->height());
painter->scale(1, -1);
}
/*if ((maskType() == 1) || (maskType() == 2) || (maskType() == 4) || (maskType() == 5))
{
if ((maskType() == 1) || (maskType() == 2))
painter->setMaskMode(1);
else
painter->setMaskMode(3);
if ((!gradientMask().isEmpty()) && (!m_Doc->docGradients.contains(gradientMask())))
gradientMaskVal = "";
if (!(gradientMask().isEmpty()) && (m_Doc->docGradients.contains(gradientMask())))
mask_gradient = m_Doc->docGradients[gradientMask()];
painter->mask_gradient = mask_gradient;
if ((maskType() == 1) || (maskType() == 4))
painter->setGradientMask(VGradient::linear, FPoint(GrMaskStartX, GrMaskStartY), FPoint(GrMaskEndX, GrMaskEndY), FPoint(GrMaskStartX, GrMaskStartY), GrMaskScale, GrMaskSkew);
else
painter->setGradientMask(VGradient::radial, FPoint(GrMaskStartX, GrMaskStartY), FPoint(GrMaskEndX, GrMaskEndY), FPoint(GrMaskFocalX, GrMaskFocalY), GrMaskScale, GrMaskSkew);
}
else if ((maskType() == 3) || (maskType() == 6) || (maskType() == 7) || (maskType() == 8))
{
if ((patternMask().isEmpty()) || (!m_Doc->docPatterns.contains(patternMask())))
painter->setMaskMode(0);
else
{
double scw = Width / groupWidth;
double sch = Height / groupHeight;
painter->setPatternMask(&m_Doc->docPatterns[patternMask()], patternMaskScaleX * scw, patternMaskScaleY * sch, patternMaskOffsetX, patternMaskOffsetY, patternMaskRotation, patternMaskSkewX, patternMaskSkewY, patternMaskMirrorX, patternMaskMirrorY);
if (maskType() == 3)
painter->setMaskMode(2);
else if (maskType() == 6)
painter->setMaskMode(4);
else if (maskType() == 7)
painter->setMaskMode(5);
else
painter->setMaskMode(6);
}
}
else*/
painter->setMaskMode(0);
painter->setFillRule(item->fillRule);
//painter->beginLayer(1.0 - fillTransparency(), fillBlendmode(), &PoLine);
painter->setMaskMode(0);
painter->scale(item->width() / item->groupWidth, item->height() / item->groupHeight);
for (int em = 0; em < item->groupItemList.count(); ++em)
{
PageItem* embedded = item->groupItemList.at(em);
painter->save();
painter->translate(embedded->gXpos, embedded->gYpos);
embedded->savedOwnPage = embedded->OwnPage;
embedded->OwnPage = item->OwnPage;
embedded->isEmbedded = true;
embedded->invalidateLayout();
drawItem(embedded, painter, QRect());
embedded->isEmbedded = false;
embedded->OwnPage = embedded->savedOwnPage;
painter->restore();
}
//painter->endLayer();
painter->restore();
}
void ScPageOutput::drawItem_ImageFrame(PageItem_ImageFrame* item, ScPainterExBase* painter, QRect clip)
{
ScPainterExBase::ImageMode mode = ScPainterExBase::rgbImages;
if ((item->fillColor() != CommonStrings::None) || (item->GrType != 0))
{
painter->setupPolygon(&item->PoLine);
fillPath(item, painter, clip);
}
if (item->Pfile.isEmpty())
{
/*painter->setPen(ScColorShade(Qt::black, 100), 1, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin);
painter->drawLine(FPoint(0, 0), FPoint(item->width(), item->height()));
painter->drawLine(FPoint(0, item->height()), FPoint(item->width(), 0));*/
}
else
{
if ((!item->imageVisible()) || (!item->imageIsAvailable))
{
/*painter->setPen(ScColorShade(Qt::red, 100), 1, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin);
painter->drawLine(FPoint(0, 0), FPoint(item->width(), item->height()));
painter->drawLine(FPoint(0, item->height()), FPoint(item->width(), 0));*/
}
else
{
ScImage scImg;
ScImage* pImage = nullptr;
double imScaleX = item->imageXScale();
double imScaleY = item->imageYScale();
if (m_reloadImages)
{
bool dummy;
bool useCmyk = false;
ScPainterExBase::ImageMode imageMode = painter->imageMode();
if (imageMode == ScPainterExBase::cmykImages)
useCmyk = true;
QFileInfo fInfo(item->Pfile);
QString ext = fInfo.suffix();
CMSettings cmsSettings(item->doc(), item->ImageProfile, item->ImageIntent);
cmsSettings.allowColorManagement(m_useProfiles);
cmsSettings.setUseEmbeddedProfile(item->UseEmbedded);
scImg.imgInfo.valid = false;
scImg.imgInfo.clipPath = "";
scImg.imgInfo.PDSpathData.clear();
scImg.imgInfo.layerInfo.clear();
scImg.imgInfo.RequestProps = item->pixm.imgInfo.RequestProps;
scImg.imgInfo.isRequest = item->pixm.imgInfo.isRequest;
scImg.loadPicture(item->Pfile, item->pixm.imgInfo.actualPageNumber, cmsSettings, translateImageModeToRequest(imageMode), m_imageRes, &dummy);
if (extensionIndicatesEPSorPS(ext) || extensionIndicatesPDF(ext))
{
imScaleX *= (72.0 / (double) m_imageRes);
imScaleY *= (72.0 / (double) m_imageRes);
}
scImg.applyEffect(item->effectsInUse, m_doc->PageColors, useCmyk);
mode = imageMode;
pImage = &scImg;
}
else
pImage = &item->pixm;
painter->save();
if (!item->imageClip.empty())
{
painter->setupPolygon(&item->imageClip);
painter->setClipPath();
}
painter->setupPolygon(&item->PoLine);
painter->setClipPath();
if (item->imageFlippedH())
{
painter->translate(item->width(), 0);
painter->scale(-1, 1);
}
if (item->imageFlippedV())
{
painter->translate(0, item->height());
painter->scale(1, -1);
}
painter->translate(item->imageXOffset() * item->imageXScale(), item->imageYOffset() * item->imageYScale());
painter->rotate(item->imageRotation());
painter->scale(imScaleX, imScaleY);
if (pImage->imgInfo.lowResType != 0)
painter->scale(pImage->imgInfo.lowResScale, pImage->imgInfo.lowResScale);
painter->drawImage(pImage, mode);
painter->restore();
}
}
}
void ScPageOutput::drawItem_Line(PageItem_Line* item, ScPainterExBase* painter, QRect clip)
{
int startArrowIndex = item->startArrowIndex();
int endArrowIndex = item->endArrowIndex();
if (item->NamedLStyle.isEmpty())
{
QString patternStrokeVal = item->strokePattern();
ScPattern *strokePattern = m_doc->checkedPattern(patternStrokeVal);
if (strokePattern)
{
if (item->patternStrokePath)
{
QPainterPath guidePath = item->PoLine.toQPainterPath(false);
guidePath.moveTo(0, 0);
guidePath.lineTo(item->width(), 0);
drawStrokePattern(item, painter, guidePath);
}
else
{
painter->setPattern(strokePattern, item->patternStrokeScaleX, item->patternStrokeScaleY, item->patternStrokeOffsetX, item->patternStrokeOffsetY, item->patternStrokeRotation, item->patternStrokeSkewX, item->patternStrokeSkewY, item->patternStrokeMirrorX, item->patternStrokeMirrorY);
painter->setStrokeMode(ScPainterExBase::Pattern);
painter->strokePath();
}
}
else if (item->strokeGradientType() > 0)
{
QString gradientStrokeVal = item->strokeGradient();
if ((!gradientStrokeVal.isEmpty()) && (!m_doc->docGradients.contains(gradientStrokeVal)))
gradientStrokeVal.clear();
if (!(gradientStrokeVal.isEmpty()) && (m_doc->docGradients.contains(gradientStrokeVal)))
painter->m_strokeGradient = VGradientEx(m_doc->docGradients[gradientStrokeVal], *m_doc);
if (painter->m_strokeGradient.stops() < 2) // fall back to solid stroking if there are not enough colorstops in the gradient.
{
if (item->lineColor() != CommonStrings::None)
{
ScColorShade strokeColor(m_doc->PageColors[item->lineColor()], item->lineShade());
painter->setBrush(strokeColor);
painter->setStrokeMode(ScPainterExBase::Solid);
}
else
painter->setStrokeMode(ScPainterExBase::None);
}
else
{
FPoint fpStart(item->GrStrokeStartX, item->GrStrokeStartY);
FPoint fpEnd(item->GrStrokeEndX, item->GrStrokeEndY);
FPoint fpFocal(item->GrStrokeFocalX, item->GrStrokeFocalY);
painter->setStrokeMode(ScPainterExBase::Gradient);
painter->m_strokeGradient = VGradientEx(item->stroke_gradient, *m_doc);
if (item->GrTypeStroke == Gradient_Linear)
painter->setGradient(VGradientEx::linear, fpStart, fpEnd, fpStart, item->GrStrokeScale, item->GrStrokeSkew);
else
painter->setGradient(VGradientEx::radial, fpStart, fpEnd, fpFocal, item->GrStrokeScale, item->GrStrokeSkew);
}
painter->drawLine(FPoint(0, 0), FPoint(item->width(), 0));
}
else if (item->lineColor() != CommonStrings::None)
{
ScColorShade scColor(m_doc->PageColors[item->lineColor()], item->lineShade());
painter->setStrokeMode(ScPainterExBase::Solid);
painter->setPen(scColor, item->lineWidth(), item->PLineArt, item->PLineEnd, item->PLineJoin);
if (item->DashValues.count() != 0)
painter->setDash(item->DashValues, item->DashOffset);
painter->drawLine(FPoint(0, 0), FPoint(item->width(), 0));
}
}
else
{
painter->setStrokeMode(ScPainterExBase::Solid);
multiLine ml = m_doc->docLineStyles[item->NamedLStyle];
for (int it = ml.size() - 1; it > -1; it--)
{
const SingleLine& sl = ml[it];
if ((sl.Color != CommonStrings::None) && (sl.Width != 0))
{
ScColorShade tmp(m_doc->PageColors[sl.Color], sl.Shade);
painter->setPen(tmp, sl.Width, static_cast<Qt::PenStyle>(sl.Dash),
static_cast<Qt::PenCapStyle>(sl.LineEnd),
static_cast<Qt::PenJoinStyle>(sl.LineJoin));
painter->drawLine(FPoint(0, 0), FPoint(item->width(), 0));
}
}
}
if (startArrowIndex != 0)
{
QTransform arrowTrans;
arrowTrans.translate(0, 0);
arrowTrans.scale(-1, 1);
drawArrow(painter, item, arrowTrans, startArrowIndex);
}
if (endArrowIndex != 0)
{
QTransform arrowTrans;
arrowTrans.translate(item->width(), 0);
drawArrow(painter, item, arrowTrans, endArrowIndex);
}
}
class ScPageOutputPainter: public TextLayoutPainter
{
private:
PageItem* m_item;
ScPainterExBase* m_painter;
ScPageOutput* m_scpage;
void setupState()
{
m_painter->setLineWidth(strokeWidth());
ScColorShade fill(m_item->doc()->PageColors[fillColor().color], fillColor().shade);
m_painter->setBrush(fill);
ScColorShade stroke(m_item->doc()->PageColors[strokeColor().color], strokeColor().shade);
m_painter->setPen(stroke, strokeWidth(), Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin);
if (matrix() != QTransform())
{
m_painter->setWorldMatrix(matrix() * m_painter->worldMatrix());
}
}
public:
ScPageOutputPainter(PageItem* item, ScPainterExBase* painter, ScPageOutput* scpage)
: m_item(item)
, m_painter(painter)
, m_scpage(scpage)
{}
void translate(double xp, double yp) override
{
TextLayoutPainter::translate(xp, yp);
m_painter->translate(xp, yp);
}
void save() override
{
TextLayoutPainter::save();
m_painter->save();
}
void restore() override
{
TextLayoutPainter::restore();
m_painter->restore();
}
void setScale(double h, double v) override
{
TextLayoutPainter::setScale(h, v);
m_painter->scale(h, v);
}
void drawGlyph(const GlyphCluster& gc) override
{
if (gc.isControlGlyphs())
return;
m_painter->save();
bool fr = m_painter->fillRule();
int fm = m_painter->fillMode();
m_painter->setFillRule(false);
m_painter->setFillMode(1);
setupState();
double sizeFactor = fontSize() / 10.0;
QVector<FPointArray> outlines = gc.glyphClusterOutline();
const QList<GlyphLayout>& glyphs = gc.glyphs();
for (int i = 0; i < glyphs.count(); ++i)
{
const FPointArray& outline = outlines.at(i);
const GlyphLayout& gl = glyphs.at(i);
m_painter->save();
m_painter->translate(gl.xoffset, - (fontSize() * gl.scaleV) + gl.yoffset);
m_painter->scale(gl.scaleH * sizeFactor, gl.scaleV * sizeFactor);
m_painter->setupPolygon(&outline, true);
if (outline.size() > 3)
m_painter->fillPath();
m_painter->restore();
m_painter->translate(gl.xadvance * gl.scaleH, 0.0);
}
m_painter->setFillMode(fm);
m_painter->setFillRule(fr);
m_painter->restore();
}
void drawGlyphOutline(const GlyphCluster& gc, bool fill) override
{
if (gc.isControlGlyphs())
return;
if (fill)
drawGlyph(gc);
m_painter->save();
bool fr = m_painter->fillRule();
m_painter->setFillRule(false);
setupState();
double current_x = 0.0;
for (const GlyphLayout& gl : gc.glyphs())
{
m_painter->save();
m_painter->translate(gl.xoffset + current_x, -(fontSize() * gc.scaleV()) + gl.yoffset);
FPointArray outline = font().glyphOutline(gl.glyph);
double scaleH = gl.scaleH * fontSize() / 10.0;
double scaleV = gl.scaleV * fontSize() / 10.0;
QTransform trans;
trans.scale(scaleH, scaleV);
outline.map(trans);
m_painter->setupPolygon(&outline, true);
if (outline.size() > 3)
{
m_painter->setLineWidth(strokeWidth());
m_painter->strokePath();
}
m_painter->restore();
current_x += gl.xadvance * gl.scaleH;
}
m_painter->setFillRule(fr);
m_painter->restore();
}
void drawLine(QPointF start, QPointF end) override
{
m_painter->save();
setupState();
m_painter->drawLine(start, end);
m_painter->restore();
}
void drawRect(QRectF rect) override
{
m_painter->save();
setupState();
m_painter->setFillMode(1);
m_painter->setStrokeMode(1);
m_painter->drawRect(rect.x(), rect.y(), rect.width(), rect.height());
m_painter->restore();
}
void drawObject(PageItem* embedded) override
{
QRect cullingArea;
if (!embedded)
return;
m_painter->save();
double pws = embedded->m_lineWidth;
embedded->invalid = true;
m_scpage->drawItem_Pre(embedded, m_painter);
switch (embedded->itemType())
{
case PageItem::ImageFrame:
case PageItem::TextFrame:
case PageItem::LatexFrame:
case PageItem::OSGFrame:
case PageItem::Polygon:
case PageItem::PathText:
case PageItem::Symbol:
case PageItem::Group:
case PageItem::RegularPolygon:
case PageItem::Arc:
case PageItem::Table:
m_scpage->drawItem(embedded, m_painter, cullingArea);
break;
case PageItem::Line:
case PageItem::PolyLine:
case PageItem::Spiral:
embedded->m_lineWidth = pws * qMin(scaleH(), scaleV());
m_scpage->drawItem(embedded, m_painter, cullingArea);
break;
default:
break;
}
embedded->m_lineWidth = pws * qMin(scaleH(), scaleV());
m_scpage->drawItem_Post(embedded, m_painter);
embedded->m_lineWidth = pws;
m_painter->restore();
}
};
void ScPageOutput::drawItem_Polygon(PageItem_Polygon* item , ScPainterExBase* painter, QRect clip)
{
painter->setupPolygon(&item->PoLine);
fillPath(item, painter, clip);
}
void ScPageOutput::drawItem_PolyLine(PageItem_PolyLine* item, ScPainterExBase* painter, QRect clip)
{
if (item->PoLine.size() < 4)
return;
int startArrowIndex = item->startArrowIndex();
int endArrowIndex = item->endArrowIndex();
if ((item->fillColor() != CommonStrings::None) || (item->GrType != 0))
{
FPointArray cli;
FPoint Start;
bool firstp = true;
for (int n = 0; n < item->PoLine.size()-3; n += 4)
{
if (firstp)
{
Start = item->PoLine.point(n);
firstp = false;
}
if (item->PoLine.isMarker(n))
{
if (n >= 2)
{
cli.addPoint(item->PoLine.point(n - 2));
cli.addPoint(item->PoLine.point(n - 2));
cli.addPoint(Start);
cli.addPoint(Start);
cli.setMarker();
}
firstp = true;
continue;
}
cli.addPoint(item->PoLine.point(n));
cli.addPoint(item->PoLine.point(n+1));
cli.addPoint(item->PoLine.point(n+2));
cli.addPoint(item->PoLine.point(n+3));
}
if (cli.size() > 2)
{
FPoint l1 = cli.point(cli.size()-2);
cli.addPoint(l1);
cli.addPoint(l1);
cli.addPoint(Start);
cli.addPoint(Start);
}
painter->setupPolygon(&cli);
fillPath(item, painter, clip);
}
painter->setupPolygon(&item->PoLine, false);
if (item->NamedLStyle.isEmpty())
{
QString patternStrokeVal = item->strokePattern();
ScPattern *strokePattern = m_doc->checkedPattern(patternStrokeVal);
if (strokePattern)
{
if (item->patternStrokePath)
{
QPainterPath guidePath = item->PoLine.toQPainterPath(false);
guidePath.moveTo(0, 0);
guidePath.lineTo(item->width(), 0);
drawStrokePattern(item, painter, guidePath);
}
else
{
painter->setPattern(strokePattern, item->patternStrokeScaleX, item->patternStrokeScaleY, item->patternStrokeOffsetX, item->patternStrokeOffsetY, item->patternStrokeRotation, item->patternStrokeSkewX, item->patternStrokeSkewY, item->patternStrokeMirrorX, item->patternStrokeMirrorY);
painter->setStrokeMode(ScPainterExBase::Pattern);
painter->strokePath();
}
}
else if (item->strokeGradientType() > 0)
{
QString gradientStrokeVal = item->strokeGradient();
if ((!gradientStrokeVal.isEmpty()) && (!m_doc->docGradients.contains(gradientStrokeVal)))
gradientStrokeVal.clear();
if (!(gradientStrokeVal.isEmpty()) && (m_doc->docGradients.contains(gradientStrokeVal)))
painter->m_strokeGradient = VGradientEx(m_doc->docGradients[gradientStrokeVal], *m_doc);
if (painter->m_strokeGradient.stops() < 2) // fall back to solid stroking if there are not enough colorstops in the gradient.
{
if (item->lineColor() != CommonStrings::None)
{
ScColorShade strokeColor(m_doc->PageColors[item->lineColor()], item->lineShade());
painter->setBrush(strokeColor);
painter->setStrokeMode(ScPainterExBase::Solid);
}
else
painter->setStrokeMode(ScPainterExBase::None);
}
else
{
FPoint fpStart(item->GrStrokeStartX, item->GrStrokeStartY);
FPoint fpEnd(item->GrStrokeEndX, item->GrStrokeEndY);
FPoint fpFocal(item->GrStrokeFocalX, item->GrStrokeFocalY);
painter->setStrokeMode(ScPainterExBase::Gradient);
painter->m_strokeGradient = VGradientEx(item->stroke_gradient, *m_doc);
if (item->GrTypeStroke == Gradient_Linear)
painter->setGradient(VGradientEx::linear, fpStart, fpEnd, fpStart, item->GrStrokeScale, item->GrStrokeSkew);
else
painter->setGradient(VGradientEx::radial, fpStart, fpEnd, fpFocal, item->GrStrokeScale, item->GrStrokeSkew);
}
painter->strokePath();
}
else if (item->lineColor() != CommonStrings::None)
{
ScColorShade scColor(m_doc->PageColors[item->lineColor()], item->lineShade());
painter->setStrokeMode(ScPainterExBase::Solid);
painter->setPen(scColor, item->lineWidth(), item->PLineArt, item->PLineEnd, item->PLineJoin);
if (item->DashValues.count() != 0)
painter->setDash(item->DashValues, item->DashOffset);
painter->strokePath();
}
}
else
{
multiLine ml = m_doc->docLineStyles[item->NamedLStyle];
for (int it = ml.size() - 1; it > -1; it--)
{
const SingleLine& sl = ml[it];
if (sl.Color != CommonStrings::None)
{
ScColorShade tmp(m_doc->PageColors[sl.Color], sl.Shade);
painter->setPen(tmp, sl.Width, static_cast<Qt::PenStyle>(sl.Dash),
static_cast<Qt::PenCapStyle>(sl.LineEnd),
static_cast<Qt::PenJoinStyle>(sl.LineJoin));
painter->strokePath();
}
}
}
if (startArrowIndex != 0)
{
FPoint Start = item->PoLine.point(0);
for (int xx = 1; xx < item->PoLine.size(); xx += 2)
{
FPoint Vector = item->PoLine.point(xx);
if ((Start.x() != Vector.x()) || (Start.y() != Vector.y()))
{
double r = atan2(Start.y() - Vector.y(), Start.x() - Vector.x()) * (180.0 / M_PI);
QTransform arrowTrans;
arrowTrans.translate(Start.x(), Start.y());
arrowTrans.rotate(r);
drawArrow(painter, item, arrowTrans, startArrowIndex);
break;
}
}
}
if (endArrowIndex != 0)
{
FPoint End = item->PoLine.point(item->PoLine.size()-2);
for (uint xx = item->PoLine.size() - 1; xx > 0; xx -= 2)
{
FPoint Vector = item->PoLine.point(xx);
if ((End.x() != Vector.x()) || (End.y() != Vector.y()))
{
double r = atan2(End.y() - Vector.y(), End.x() - Vector.x()) * (180.0 / M_PI);
QTransform arrowTrans;
arrowTrans.translate(End.x(), End.y());
arrowTrans.rotate(r);
drawArrow(painter, item, arrowTrans, endArrowIndex);
break;
}
}
}
}
void ScPageOutput::drawItem_RegularPolygon(PageItem_RegularPolygon* item, ScPainterExBase* painter, QRect clip)
{
painter->setupPolygon(&item->PoLine);
painter->fillPath();
}
void ScPageOutput::drawItem_Spiral(PageItem_Spiral* item, ScPainterExBase* painter, QRect clip)
{
if (item->PoLine.size() < 4)
return;
int startArrowIndex = item->startArrowIndex();
int endArrowIndex = item->endArrowIndex();
if ((item->fillColor() != CommonStrings::None) || (item->GrType != 0))
{
FPointArray cli;
FPoint Start;
bool firstp = true;
for (int n = 0; n < item->PoLine.size()-3; n += 4)
{
if (firstp)
{
Start = item->PoLine.point(n);
firstp = false;
}
if (item->PoLine.isMarker(n))
{
cli.addPoint(item->PoLine.point(n-2));
cli.addPoint(item->PoLine.point(n-2));
cli.addPoint(Start);
cli.addPoint(Start);
cli.setMarker();
firstp = true;
continue;
}
cli.addPoint(item->PoLine.point(n));
cli.addPoint(item->PoLine.point(n+1));
cli.addPoint(item->PoLine.point(n+2));
cli.addPoint(item->PoLine.point(n+3));
}
if (cli.size() > 2)
{
FPoint l1 = cli.point(cli.size()-2);
cli.addPoint(l1);
cli.addPoint(l1);
cli.addPoint(Start);
cli.addPoint(Start);
}
painter->setupPolygon(&cli);
fillPath(item, painter, clip);
}
painter->setupPolygon(&item->PoLine, false);
if (item->NamedLStyle.isEmpty())
{
QString patternStrokeVal = item->strokePattern();
ScPattern *strokePattern = m_doc->checkedPattern(patternStrokeVal);
if (strokePattern)
{
if (item->patternStrokePath)
{
QPainterPath guidePath = item->PoLine.toQPainterPath(false);
guidePath.moveTo(0, 0);
guidePath.lineTo(item->width(), 0);
drawStrokePattern(item, painter, guidePath);
}
else
{
painter->setPattern(strokePattern, item->patternStrokeScaleX, item->patternStrokeScaleY, item->patternStrokeOffsetX, item->patternStrokeOffsetY, item->patternStrokeRotation, item->patternStrokeSkewX, item->patternStrokeSkewY, item->patternStrokeMirrorX, item->patternStrokeMirrorY);
painter->setStrokeMode(ScPainterExBase::Pattern);
painter->strokePath();
}
}
else if (item->strokeGradientType() > 0)
{
QString gradientStrokeVal = item->strokeGradient();
if ((!gradientStrokeVal.isEmpty()) && (!m_doc->docGradients.contains(gradientStrokeVal)))
gradientStrokeVal.clear();
if (!(gradientStrokeVal.isEmpty()) && (m_doc->docGradients.contains(gradientStrokeVal)))
painter->m_strokeGradient = VGradientEx(m_doc->docGradients[gradientStrokeVal], *m_doc);
if (painter->m_strokeGradient.stops() < 2) // fall back to solid stroking if there are not enough colorstops in the gradient.
{
if (item->lineColor() != CommonStrings::None)
{
ScColorShade strokeColor(m_doc->PageColors[item->lineColor()], item->lineShade());
painter->setBrush(strokeColor);
painter->setStrokeMode(ScPainterExBase::Solid);
}
else
painter->setStrokeMode(ScPainterExBase::None);
}
else
{
FPoint fpStart(item->GrStrokeStartX, item->GrStrokeStartY);
FPoint fpEnd(item->GrStrokeEndX, item->GrStrokeEndY);
FPoint fpFocal(item->GrStrokeFocalX, item->GrStrokeFocalY);
painter->setStrokeMode(ScPainterExBase::Gradient);
painter->m_strokeGradient = VGradientEx(item->stroke_gradient, *m_doc);
if (item->GrTypeStroke == Gradient_Linear)
painter->setGradient(VGradientEx::linear, fpStart, fpEnd, fpStart, item->GrStrokeScale, item->GrStrokeSkew);
else
painter->setGradient(VGradientEx::radial, fpStart, fpEnd, fpFocal, item->GrStrokeScale, item->GrStrokeSkew);
}
painter->strokePath();
}
else if (item->lineColor() != CommonStrings::None)
{
ScColorShade scColor(m_doc->PageColors[item->lineColor()], item->lineShade());
painter->setStrokeMode(ScPainterExBase::Solid);
painter->setPen(scColor, item->lineWidth(), item->PLineArt, item->PLineEnd, item->PLineJoin);
if (item->DashValues.count() != 0)
painter->setDash(item->DashValues, item->DashOffset);
painter->strokePath();
}
}
else
{
multiLine ml = m_doc->docLineStyles[item->NamedLStyle];
for (int it = ml.size() - 1; it > -1; it--)
{
const SingleLine& sl = ml[it];
if (sl.Color != CommonStrings::None)
{
ScColorShade tmp(m_doc->PageColors[sl.Color], sl.Shade);
painter->setPen(tmp, sl.Width, static_cast<Qt::PenStyle>(sl.Dash),
static_cast<Qt::PenCapStyle>(sl.LineEnd),
static_cast<Qt::PenJoinStyle>(sl.LineJoin));
painter->strokePath();
}
}
}
if (startArrowIndex != 0)
{
FPoint Start = item->PoLine.point(0);
for (int xx = 1; xx < item->PoLine.size(); xx += 2)
{
FPoint Vector = item->PoLine.point(xx);
if ((Start.x() != Vector.x()) || (Start.y() != Vector.y()))
{
double r = atan2(Start.y() - Vector.y(), Start.x() - Vector.x()) * (180.0 / M_PI);
QTransform arrowTrans;
arrowTrans.translate(Start.x(), Start.y());
arrowTrans.rotate(r);
drawArrow(painter, item, arrowTrans, startArrowIndex);
break;
}
}
}
if (endArrowIndex != 0)
{
FPoint End = item->PoLine.point(item->PoLine.size()-2);
for (uint xx = item->PoLine.size() - 1; xx > 0; xx -= 2)
{
FPoint Vector = item->PoLine.point(xx);
if ((End.x() != Vector.x()) || (End.y() != Vector.y()))
{
double r = atan2(End.y() - Vector.y(), End.x() - Vector.x()) * (180.0 / M_PI);
QTransform arrowTrans;
arrowTrans.translate(End.x(), End.y());
arrowTrans.rotate(r);
drawArrow(painter, item, arrowTrans, endArrowIndex);
break;
}
}
}
}
void ScPageOutput::drawItem_Table(PageItem_Table* item, ScPainterExBase* painter, QRect clip)
{
painter->save();
// Set the clip path.
painter->setupPolygon(&item->PoLine);
painter->setClipPath();
// Paint the table.
CollapsedTablePainterEx tablePainter(this, item);
tablePainter.paintTable(painter);
painter->restore();
}
void ScPageOutput::drawItem_Text(PageItem* item, ScPainterExBase* painter, QRect cullingArea)
{
if (item->pathTextShowFrame())
{
painter->setupPolygon(&item->PoLine, false);
if (item->NamedLStyle.isEmpty())
{
if (item->lineColor() != CommonStrings::None)
painter->strokePath();
}
else
{
multiLine ml = m_doc->docLineStyles[item->NamedLStyle];
for (int it = ml.size() - 1; it > -1; it--)
{
const SingleLine& sl = ml[it];
if ((sl.Color != CommonStrings::None) && (sl.Width != 0))
{
ScColorShade tmp(m_doc->PageColors[sl.Color], sl.Shade);
painter->setPen(tmp, sl.Width, static_cast<Qt::PenStyle>(sl.Dash),
static_cast<Qt::PenCapStyle>(sl.LineEnd),
static_cast<Qt::PenJoinStyle>(sl.LineJoin));
painter->drawLine(FPoint(0, 0), FPoint(item->width(), 0));
}
}
}
}
painter->save();
if ((item->fillColor() != CommonStrings::None) || (item->GrType != 0))
{
painter->setupPolygon(&item->PoLine);
fillPath(item, painter, cullingArea);
}
if ((item->isAnnotation()) && (item->annotation().Type() == Annotation::Button) && (!item->Pfile.isEmpty()) && (item->imageIsAvailable) && (item->imageVisible()) && (item->annotation().UseIcons()))
{
painter->save();
painter->setupPolygon(&item->PoLine);
painter->setClipPath();
painter->scale(item->imageXScale(), item->imageYScale());
painter->translate(static_cast<int>(item->imageXOffset() * item->imageXScale()), static_cast<int>(item->imageYOffset() * item->imageYScale()));
if (!item->pixm.qImage().isNull())
painter->drawImage(&item->pixm, ScPainterExBase::rgbImages);
painter->restore();
}
if (item->isMasterItem())
{
// relayout necessary to get page number ok
item->invalidateLayout();
item->layout();
}
ScPageOutputPainter p(item, painter, this);
item->textLayout.renderBackground(&p);
item->textLayout.render(&p);
painter->restore();
}
void ScPageOutput::drawArrow(ScPainterExBase* painter, PageItem* item, QTransform &arrowTrans, int arrowIndex)
{
FPointArray arrow = m_doc->arrowStyles().at(arrowIndex - 1).points.copy();
if (item->NamedLStyle.isEmpty())
{
if (item->lineWidth() != 0.0)
arrowTrans.scale(item->lineWidth(), item->lineWidth());
}
else
{
multiLine ml = m_doc->docLineStyles[item->NamedLStyle];
if (ml[ml.size() - 1].Width != 0.0)
arrowTrans.scale(ml[ml.size() - 1].Width, ml[ml.size() - 1].Width);
}
arrow.map(arrowTrans);
painter->setupPolygon(&arrow);
if (item->NamedLStyle.isEmpty())
{
if (item->lineColor() != CommonStrings::None)
{
ScColorShade tmp(m_doc->PageColors[item->lineColor()], item->lineShade());
painter->setBrush(tmp);
painter->setBrushOpacity(1.0 - item->lineTransparency());
painter->setLineWidth(0);
painter->setFillMode(ScPainterExBase::Solid);
painter->fillPath();
}
}
else
{
multiLine ml = m_doc->docLineStyles[item->NamedLStyle];
if (ml[0].Color != CommonStrings::None)
{
ScColorShade tmp(m_doc->PageColors[ml[0].Color], ml[0].Shade);
painter->setBrush(tmp);
painter->setLineWidth(0);
painter->setFillMode(ScPainterExBase::Solid);
painter->fillPath();
}
for (int it = ml.size() - 1; it > 0; it--)
{
if (ml[it].Color != CommonStrings::None)
{
ScColorShade tmp(m_doc->PageColors[ml[it].Color], ml[it].Shade);
painter->setPen(tmp, ml[it].Width, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin);
painter->strokePath();
}
}
}
}
void ScPageOutput::drawMarks(ScPage* page, ScPainterExBase* painter, const MarksOptions& options)
{
double markLength = options.markLength;
double markOffs = options.markOffset;
double bleedLeft = 0.0, bleedRight = 0.0;
double bleedBottom = options.BleedBottom;
double bleedTop = options.BleedTop;
if (!options.cropMarks && !options.bleedMarks && !options.registrationMarks && !options.colorMarks)
return;
if (m_doc->locationOfPage(page->pageNr()) == LeftPage)
{
bleedRight = options.BleedRight;
bleedLeft = options.BleedLeft;
}
else if (m_doc->locationOfPage(page->pageNr()) == RightPage)
{
bleedRight = options.BleedLeft;
bleedLeft = options.BleedRight;
}
else
{
bleedRight = options.BleedLeft;
bleedLeft = options.BleedLeft;
}
double width = page->width();
double height = page->height();
double offsetX = page->xOffset();
double offsetY = page->yOffset();
QPointF bleedTopLeft(offsetX - bleedLeft, offsetY - bleedTop);
QPointF bleedBottomRight(offsetX + width + bleedRight, offsetY + height + bleedBottom);
QRectF bleedBox(bleedTopLeft, bleedBottomRight);
painter->save();
painter->setLineWidth(0.5);
painter->setPen(ScColorShade(Qt::black, 100), 0.5, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin);
if (options.cropMarks)
{
FPoint start, end;
double left = offsetX, right = offsetX + width;
double bottom = offsetY + height, top = offsetY;
drawBoxMarks(painter, QRectF(QPointF(left, top), QPointF(right, bottom)), bleedBox, markOffs, markLength);
}
if (options.bleedMarks)
{
FPoint start, end;
double left = offsetX - bleedLeft, right = offsetX + width + bleedRight;
double bottom = offsetY + height + bleedBottom, top = offsetY - bleedTop;;
drawBoxMarks(painter, QRectF(QPointF(left, top), QPointF(right, bottom)), bleedBox, markOffs, markLength);
}
if (options.registrationMarks)
{
double posX = (2* offsetX + width) / 2.0 - 7.0;
double posY = (offsetY + height + bleedBottom + markOffs + 3.0);
painter->save();
painter->translate(posX, posY);
drawRegistrationCross(painter);
painter->restore();
posX = (2 * offsetX + width) / 2.0 - 7.0;
posY = (offsetY - bleedTop - markOffs - 17);
painter->save();
painter->translate(posX, posY);
drawRegistrationCross(painter);
painter->restore();
posX = (offsetX - bleedLeft - markOffs - 17);
posY = (2 * offsetY + height) / 2.0 - 7.0;
painter->save();
painter->translate(posX, posY);
drawRegistrationCross(painter);
painter->restore();
posX = (offsetX + width + bleedRight + markOffs + 3.0);
posY = (2 * offsetY + height) / 2.0 - 7.0;
painter->save();
painter->translate(posX, posY);
drawRegistrationCross(painter);
painter->restore();
}
if (options.colorMarks)
{
int shade = 100;
double startX = offsetX + 6.0;
double startY = offsetY - bleedTop - markOffs - 16.0;
ScColorShade strokecolor(ScColor(0, 0, 0, 255), 100);
painter->setPen(strokecolor, 0.5, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin);
painter->setFillMode(ScPainterExBase::Solid);
for (int i = 0; i < 11; i++)
{
ScColorShade fillcolor(ScColor(0, 0, 0, 255), shade);
painter->setBrush(fillcolor);
painter->drawRect(startX + i * 14, startY, 14, 14);
shade -= 10;
}
startX = offsetX + width - 20.0;
painter->setBrush(ScColorShade(ScColor(0, 0, 0, 255), 50));
painter->drawRect(startX, startY, 14, 14);
startX -= 14;
painter->setBrush(ScColorShade(ScColor(0, 0, 255, 0), 50));
painter->drawRect(startX, startY, 14, 14);
startX -= 14;
painter->setBrush(ScColorShade(ScColor(0, 255, 0, 0), 50));
painter->drawRect(startX, startY, 14, 14);
startX -= 14;
painter->setBrush(ScColorShade(ScColor(255, 0, 0, 0), 50));
painter->drawRect(startX, startY, 14, 14);
startX -= 14;
painter->setBrush(ScColorShade(ScColor(255, 255, 0, 0), 100));
painter->drawRect(startX, startY, 14, 14);
startX -= 14;
painter->setBrush(ScColorShade(ScColor(255, 0, 255, 0), 100));
painter->drawRect(startX, startY, 14, 14);
startX -= 14;
painter->setBrush(ScColorShade(ScColor(0, 255, 255, 0), 100));
painter->drawRect(startX, startY, 14, 14);
startX -= 14;
painter->setBrush(ScColorShade(ScColor(0, 0, 0, 255), 100));
painter->drawRect(startX, startY, 14, 14);
startX -= 14;
painter->setBrush(ScColorShade(ScColor(0, 0, 255, 0), 100));
painter->drawRect(startX, startY, 14, 14);
startX -= 14;
painter->setBrush(ScColorShade(ScColor(0, 255, 0, 0), 100));
painter->drawRect(startX, startY, 14, 14);
startX -= 14;
painter->setBrush(ScColorShade(ScColor(255, 0, 0, 0), 100));
painter->drawRect(startX, startY, 14, 14);
}
painter->restore();
}
void ScPageOutput::drawBoxMarks(ScPainterExBase* painter, const QRectF& box, const QRectF& bleedBox, double offset , double markSize)
{
FPoint start, end;
double left = box.left(), right = box.right();
double bottom = box.bottom(), top = box.top();
double bleedLeft = bleedBox.left(), bleedRight = bleedBox.right();
double bleedBottom = bleedBox.bottom(), bleedTop = bleedBox.top();
// Top Left
start.setXY(bleedLeft - offset, top);
end.setXY (bleedLeft - offset - markSize, top);
painter->drawLine(start, end);
start.setXY(left, bleedTop - offset);
end.setXY (left, bleedTop - offset - markSize);
painter->drawLine(start, end);
// Top Right
start.setXY(bleedRight + offset, top);
end.setXY (bleedRight + offset + markSize, top);
painter->drawLine(start, end);
start.setXY(right, bleedTop - offset);
end.setXY (right, bleedTop - offset - markSize);
painter->drawLine(start, end);
// Bottom Left
start.setXY(bleedLeft - offset, bottom);
end.setXY (bleedLeft - offset - markSize, bottom);
painter->drawLine(start, end);
start.setXY(left, bleedBottom + offset);
end.setXY (left, bleedBottom + offset + markSize);
painter->drawLine(start, end);
// Bottom Right
start.setXY(bleedRight + offset, bottom);
end.setXY (bleedRight + offset + markSize, bottom);
painter->drawLine(start, end);
start.setXY(right, bleedBottom + offset);
end.setXY (right, bleedBottom + offset + markSize);
painter->drawLine(start, end);
}
void ScPageOutput::drawRegistrationCross(ScPainterExBase* painter)
{
painter->save();
painter->newPath();
painter->moveTo(0.0, 7.0);
painter->lineTo(14.0, 7.0);
painter->strokePath();
painter->newPath();
painter->moveTo(7.0, 0.0);
painter->lineTo(7.0, 14.0);
painter->strokePath();
painter->newPath();
painter->moveTo(13.0, 7.0);
painter->curveTo(FPoint(13.0, 10.31383), FPoint(10.31383, 13.0), FPoint(7.0, 13.0));
painter->curveTo(FPoint(3.68629, 13.0) , FPoint(1.0, 10.31383) , FPoint(1.0, 7.0));
painter->curveTo(FPoint(1.0, 3.68629) , FPoint(3.68629, 1.0) , FPoint(7.0, 1.0));
painter->curveTo(FPoint(10.31383, 1.0) , FPoint(13.0, 3.68629) , FPoint(13.0, 7.0));
painter->strokePath();
painter->newPath();
painter->moveTo(10.5, 7.0);
painter->curveTo(FPoint(10.5, 8.93307), FPoint(8.93307, 10.5), FPoint(7.0, 10.5));
painter->curveTo(FPoint(5.067, 10.5) , FPoint(3.5, 8.93307) , FPoint(3.5, 7.0));
painter->curveTo(FPoint(3.5, 5.067) , FPoint(5.067, 3.5) , FPoint(7.0, 3.5));
painter->curveTo(FPoint(8.93307, 3.5) , FPoint(10.5, 5.067) , FPoint(10.5, 7.0));
painter->strokePath();
painter->restore();
}
void ScPageOutput::fillPath(PageItem* item, ScPainterExBase* painter, QRect clip)
{
if (painter->fillMode() == ScPainterExBase::Pattern && !painter->hasCapability(ScPainterExBase::patterns))
drawPattern(item, painter, clip);
else
painter->fillPath();
}
void ScPageOutput::strokePath(PageItem* item, ScPainterExBase* painter, QRect clip)
{
painter->strokePath();
}