Subversion Repositories Scribus

Rev

Rev 24617 | 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.
*/

/***************************************************************************
                          pageitem.cpp  -  description
                             -------------------
    begin                : Sat Apr 7 2001
    copyright            : (C) 2001 by Franz Schmid
    email                : Franz.Schmid@altmuehlnet.de
 ***************************************************************************/


/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/


#include "pageitem.h"

#include <QDebug>
#include <QFileInfo>
#include <QFont>
#include <QMessageBox>
#include <QPainter>
#include <QPen>
#include <QPoint>
#include <QPointF>
#include <QPolygon>
#include <QRegExp>
#include <QRegion>
#include <QRegularExpression>
#include <cairo.h>
#include <cassert>
#include <qdrawutil.h>
#include <sstream>

#include "appmodes.h"
#include "canvas.h"
#include "canvasmode.h"
#include "cmsettings.h"
#include "colorblind.h"
#include "desaxe/saxXML.h"
#include "iconmanager.h"
#include "marks.h"
#include "pageitem_arc.h"
#include "pageitem_group.h"
#include "pageitem_latexframe.h"
#include "pageitem_line.h"
#include "pageitem_noteframe.h"
#include "pageitem_regularpolygon.h"
#include "pageitem_spiral.h"
#include "pageitem_table.h"
#include "pageitem_textframe.h"
#include "prefsmanager.h"
#include "resourcecollection.h"
#include "scclocale.h"
#include "sccolorengine.h"
#include "scimagecacheproxy.h"
#include "sclimits.h"
#include "scpage.h"
#include "scpainter.h"
#include "scpaths.h"
#include "scpattern.h"
#include "scribusapp.h"
#include "scribuscore.h"
#include "scribusdoc.h"
#include "scribusview.h"
#include "scribuswin.h"
#include "sctextstream.h"
#include "selection.h"
#include "text/storytext.h"
#include "ui/contentpalette.h"
#include "ui/guidemanager.h"
#include "ui/propertiespalette.h"
#include "undomanager.h"
#include "undostate.h"
#include "units.h"
#include "util.h"
#include "util_file.h"
#include "util_formats.h"
#include "util_math.h"
#include "util_text.h"




using namespace std;

PageItem::PageItem(const PageItem & other)
        : QObject(other.parent()),
         UndoObject(other),
         SingleObservable<PageItem>(other.m_Doc->itemsChanged()),
         TextContext(this),

// 200 attributes! That is madness, or to quote some famous people from Kriquet:
// "THAT ALL HAS TO GO!"
        gXpos(other.gXpos),
        gYpos(other.gYpos),
        gWidth(other.gWidth),
        gHeight(other.gHeight),
        GrType(other.GrType),
        GrStartX(other.GrStartX),
        GrStartY(other.GrStartY),
        GrEndX(other.GrEndX),
        GrEndY(other.GrEndY),
        GrFocalX(other.GrFocalX),
        GrFocalY(other.GrFocalY),
        GrScale(other.GrScale),
        GrSkew(other.GrSkew),
        GrExtend(other.GrExtend),
        GrControl1(other.GrControl1),
        GrControl2(other.GrControl2),
        GrControl3(other.GrControl3),
        GrControl4(other.GrControl4),
        GrControl5(other.GrControl5),
        GrColorP1(other.GrColorP1),
        GrColorP2(other.GrColorP2),
        GrColorP3(other.GrColorP3),
        GrColorP4(other.GrColorP4),
        GrCol1transp(other.GrCol1transp),
        GrCol2transp(other.GrCol2transp),
        GrCol3transp(other.GrCol3transp),
        GrCol4transp(other.GrCol4transp),
        GrCol1Shade(other.GrCol1Shade),
        GrCol2Shade(other.GrCol2Shade),
        GrCol3Shade(other.GrCol3Shade),
        GrCol4Shade(other.GrCol4Shade),
        meshGradientPatches(other.meshGradientPatches),
        meshGradientArray(other.meshGradientArray),
        selectedMeshPointX(other.selectedMeshPointX),
        selectedMeshPointY(other.selectedMeshPointY),
        selectedMeshControlPoint(other.selectedMeshControlPoint),
        snapToPatchGrid(other.snapToPatchGrid),
        m_columns(other.m_columns),
        m_columnGap(other.m_columnGap),
        PLineArt(other.PLineArt),
        PLineEnd(other.PLineEnd),
        PLineJoin(other.PLineJoin),
        NamedLStyle(other.NamedLStyle),
        Clip(other.Clip),
        PoLine(other.PoLine),
        ContourLine(other.ContourLine),
        imageClip(other.imageClip),
        Segments(other.Segments),
        effectsInUse(other.effectsInUse),
        PoShow(other.PoShow),
        BaseOffs(other.BaseOffs),
        textPathType(other.textPathType),
        textPathFlipped(other.textPathFlipped),
        ClipEdited(other.ClipEdited),
        FrameType(other.FrameType),
        OwnPage(other.OwnPage),
        oldOwnPage(other.oldOwnPage),
        pixm(other.pixm),
        Pfile(other.Pfile),
        Pfile2(other.Pfile2),
        Pfile3(other.Pfile3),
        ImageProfile(other.ImageProfile),
        UseEmbedded(other.UseEmbedded),
        EmbeddedProfile(other.EmbeddedProfile),
        ImageIntent(other.ImageIntent),
        OverrideCompressionMethod(other.OverrideCompressionMethod),
        CompressionMethodIndex(other.CompressionMethodIndex),
        OverrideCompressionQuality(other.OverrideCompressionQuality),
        CompressionQualityIndex(other.CompressionQualityIndex),

        imageIsAvailable(other.imageIsAvailable),
        OrigW(other.OrigW),
        OrigH(other.OrigH),
        BBoxX(other.BBoxX),
        BBoxH(other.BBoxH),
        CurX(other.CurX),
        CurY(other.CurY),
        itemText(other.itemText),
        textLayout(&itemText, this),
        isBookmark(other.isBookmark),
        HasSel(other.HasSel),
        isAutoText(other.isAutoText),
        inPdfArticle(other.inPdfArticle),
        isRaster(other.isRaster),
        OldB(other.OldB),
        OldH(other.OldH),
        OldB2(other.OldB2),
        OldH2(other.OldH2),
        Sizing(other.Sizing),
        m_layerID(other.m_layerID),
        ScaleType(other.ScaleType),
        AspectRatio(other.AspectRatio),
        DashValues(other.DashValues),
        DashOffset(other.DashOffset),
        fill_gradient(other.fill_gradient),
        fillRule(other.fillRule),
        doOverprint(other.doOverprint),
        m_leftLink(other.m_leftLink),
        m_rightLink(other.m_rightLink),
        m_topLink(other.m_topLink),
        m_bottomLink(other.m_bottomLink),
        LeftLinkID(other.LeftLinkID),
        RightLinkID(other.RightLinkID),
        TopLinkID(other.TopLinkID),
        BottomLinkID(other.BottomLinkID),
        LeftLine(other.LeftLine),
        RightLine(other.RightLine),
        TopLine(other.TopLine),
        BottomLine(other.BottomLine),
        isTableItem(other.isTableItem),
        isSingleSel(other.isSingleSel),
        groupItemList(other.groupItemList),
        groupWidth(other.groupWidth),
        groupHeight(other.groupHeight),
        BoundingX(other.BoundingX),
        BoundingY(other.BoundingY),
        BoundingW(other.BoundingW),
        BoundingH(other.BoundingH),
        ChangedMasterItem(other.ChangedMasterItem),
        OnMasterPage(other.OnMasterPage),
        isEmbedded(other.isEmbedded),
        m_roundedCornerRadius(other.m_roundedCornerRadius),
        oldXpos(other.oldXpos),
        oldYpos(other.oldYpos),
        oldWidth(other.oldWidth),
        oldHeight(other.oldHeight),
        oldRot(other.oldRot),
        oldLocalScX(other.oldLocalScX),
        oldLocalScY(other.oldLocalScY),
        oldLocalX(other.oldLocalX),
        oldLocalY(other.oldLocalY),
        m_Doc(other.m_Doc),
        m_lineWidth(other.m_lineWidth),
        m_oldLineWidth(other.m_oldLineWidth),
        patternStrokeVal(other.patternStrokeVal),
        patternStrokeScaleX(other.patternStrokeScaleX),
        patternStrokeScaleY(other.patternStrokeScaleY),
        patternStrokeOffsetX(other.patternStrokeOffsetX),
        patternStrokeOffsetY(other.patternStrokeOffsetY),
        patternStrokeRotation(other.patternStrokeRotation),
        patternStrokeSkewX(other.patternStrokeSkewX),
        patternStrokeSkewY(other.patternStrokeSkewY),
        patternStrokeSpace(other.patternStrokeSpace),
        patternStrokeMirrorX(other.patternStrokeMirrorX),
        patternStrokeMirrorY(other.patternStrokeMirrorY),
        patternStrokePath(other.patternStrokePath),
        gradientStrokeVal(other.gradientStrokeVal),
        stroke_gradient(other.stroke_gradient),
        GrTypeStroke(other.GrTypeStroke),
        GrStrokeStartX(other.GrStrokeStartX),
        GrStrokeStartY(other.GrStrokeStartY),
        GrStrokeEndX(other.GrStrokeEndX),
        GrStrokeEndY(other.GrStrokeEndY),
        GrStrokeFocalX(other.GrStrokeFocalX),
        GrStrokeFocalY(other.GrStrokeFocalY),
        GrStrokeScale(other.GrStrokeScale),
        GrStrokeSkew(other.GrStrokeSkew),
        GrMask(other.GrMask),
        GrMaskStartX(other.GrMaskStartX),
        GrMaskStartY(other.GrMaskStartY),
        GrMaskEndX(other.GrMaskEndX),
        GrMaskEndY(other.GrMaskEndY),
        GrMaskFocalX(other.GrMaskFocalX),
        GrMaskFocalY(other.GrMaskFocalY),
        GrMaskScale(other.GrMaskScale),
        GrMaskSkew(other.GrMaskSkew),
        patternMaskScaleX(other.patternMaskScaleX),
        patternMaskScaleY(other.patternMaskScaleY),
        patternMaskOffsetX(other.patternMaskOffsetX),
        patternMaskOffsetY(other.patternMaskOffsetY),
        patternMaskRotation(other.patternMaskRotation),
        patternMaskSkewX(other.patternMaskSkewX),
        patternMaskSkewY(other.patternMaskSkewY),
        patternMaskMirrorX(other.patternMaskMirrorX),
        patternMaskMirrorY(other.patternMaskMirrorY),
        patternMaskVal(other.patternMaskVal),
        mask_gradient(other.mask_gradient),
        hatchAngle(other.hatchAngle),
        hatchDistance(other.hatchDistance),
        hatchType(other.hatchType),
        hatchUseBackground(other.hatchUseBackground),
        hatchBackground(other.hatchBackground),
        hatchForeground(other.hatchForeground),
        hatchBackgroundQ(other.hatchBackgroundQ),
        hatchForegroundQ(other.hatchForegroundQ),
        // protected
        undoManager(other.undoManager),
        firstChar(0),   // since this box is unlinked now
        m_maxChars(0),   // since the layout is invalid now
        m_sampleItem(false),
        m_textDistanceMargins(other.m_textDistanceMargins),
        verticalAlign(other.verticalAlign),
        m_itemType(other.m_itemType),
        m_itemName(other.m_itemName),
        m_isAnnotation(other.m_isAnnotation),
        m_annotation(other.m_annotation),
        m_gradientName(other.m_gradientName),
        m_patternName(other.m_patternName),
        patternScaleX(other.patternScaleX),
        patternScaleY(other.patternScaleY),
        patternOffsetX(other.patternOffsetX),
        patternOffsetY(other.patternOffsetY),
        patternRotation(other.patternRotation),
        patternSkewX(other.patternSkewX),
        patternSkewY(other.patternSkewY),
        patternMirrorX(other.patternMirrorX),
        patternMirrorY(other.patternMirrorY),
        m_fillColor(other.m_fillColor),
        m_lineColor(other.m_lineColor),
        m_lineShade(other.m_lineShade),
        m_fillShade(other.m_fillShade),
        m_fillTransparency(other.m_fillTransparency),
        m_lineTransparency(other.m_lineTransparency),
        m_fillBlendMode(other.m_fillBlendMode),
        m_lineBlendMode(other.m_lineBlendMode),
        m_ImageIsFlippedH(other.m_ImageIsFlippedH),
        m_ImageIsFlippedV(other.m_ImageIsFlippedV),
        m_Locked(other.m_Locked),
        m_SizeLocked(other.m_SizeLocked),
        m_SizeHLocked(other.m_SizeHLocked),
        m_SizeVLocked(other.m_SizeVLocked),
        m_textFlowMode(other.m_textFlowMode),
        pageItemAttributes(other.pageItemAttributes),
        m_PrintEnabled(other.m_PrintEnabled),
        m_fillQColor(other.m_fillQColor),
        m_strokeQColor(other.m_strokeQColor),
        m_grQColorP1(other.m_grQColorP1),
        m_grQColorP2(other.m_grQColorP2),
        m_grQColorP3(other.m_grQColorP3),
        m_grQColorP4(other.m_grQColorP4),
        m_xPos(other.m_xPos),
        m_yPos(other.m_yPos),
        m_width(other.m_width),
        m_height(other.m_height),
        m_rotation(other.m_rotation),
        m_isSelected(other.m_isSelected),
        m_imageVisible(other.m_imageVisible),
        m_imageXScale(other.m_imageXScale),
        m_imageYScale(other.m_imageYScale),
        m_imageXOffset(other.m_imageXOffset),
        m_imageYOffset(other.m_imageYOffset),
        m_imageRotation(other.m_imageRotation),
        m_firstLineOffset(other.m_firstLineOffset),
        m_groupClips(other.m_groupClips),
        m_startArrowIndex(other.m_startArrowIndex),
        m_endArrowIndex(other.m_endArrowIndex),
        m_startArrowScale(other.m_startArrowScale),
        m_endArrowScale(other.m_endArrowScale),
        m_hasSoftShadow(other.m_hasSoftShadow),
        m_softShadowColor(other.m_softShadowColor),
        m_softShadowShade(other.m_softShadowShade),
        m_softShadowBlurRadius(other.m_softShadowBlurRadius),
        m_softShadowXOffset(other.m_softShadowXOffset),
        m_softShadowYOffset(other.m_softShadowYOffset),
        m_softShadowOpacity(other.m_softShadowOpacity),
        m_softShadowBlendMode(other.m_softShadowBlendMode),
        m_softShadowErasedByObject(other.m_softShadowErasedByObject),
        m_softShadowHasObjectTransparency(other.m_softShadowHasObjectTransparency)
{
        QString tmp;
        m_imageVisible = m_Doc->guidesPrefs().showPic;
        m_Doc->TotalItems++;
       
        QString oldName(m_itemName);
        int nameNum = m_Doc->TotalItems;
        m_itemName += tmp.setNum(m_Doc->TotalItems);
        while (m_Doc->itemNameExists(m_itemName))
        {
                ++nameNum;
                m_itemName = oldName + tmp.setNum(nameNum);
        }
       
        uniqueNr = m_Doc->TotalItems;
        invalid = true;
        if (other.isInlineImage)
        {
                QFileInfo inlFi(Pfile);
                QString ext = inlFi.suffix();
                QTemporaryFile *tempFile = new QTemporaryFile(QDir::tempPath() + "/scribus_temp_XXXXXX." + ext);
                tempFile->setAutoRemove(false);
                tempFile->open();
                QString fileName = getLongPathName(tempFile->fileName());
                tempFile->close();
                copyFile(Pfile, fileName);
                Pfile = fileName;
                delete tempFile;
                isInlineImage = true;
                isTempFile = true;
        }
        else
        {
                isInlineImage = false;
                isTempFile = false;
        }
        Parent = nullptr;
        unWeld();
}


PageItem::PageItem(ScribusDoc *doc, ItemType newType, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline)
        // Initialize superclass(es)
        : QObject(doc), SingleObservable<PageItem>(doc->itemsChanged()), TextContext(this),
        // Initialize member variables
        itemText(doc),
        textLayout(&itemText, this),
        undoManager(UndoManager::instance())
{
        m_Doc = doc;
        QString tmp;
        gXpos = oldXpos = m_xPos = x;
        gYpos = oldYpos = m_yPos = y;
        //CB Surely we can remove some of these?
        OldB2 = OldB = oldWidth = m_width = w;
        OldH2 = OldH = oldHeight = m_height = h;
        BoundingX = x;
        BoundingY = y;
        BoundingW = w;
        BoundingH = h;
        m_itemType = newType;
        m_fillColor = fill;
        m_lineColor = m_itemType == PageItem::TextFrame ? fill : outline;
        GrEndX = w;

        GrControl2 = FPoint(w, 0);
        GrControl3 = FPoint(w, h);
        GrControl4 = FPoint(0, h);
        GrControl5 = FPoint(w / 2.0, h / 2.0);
        GrStrokeEndX = w;
        m_lineWidth = w2;
        m_oldLineWidth = w2;
        PLineArt = Qt::PenStyle(m_Doc->itemToolPrefs().shapeLineStyle);
        PLineEnd = Qt::FlatCap;
        PLineJoin = Qt::MiterJoin;
        m_textDistanceMargins = m_Doc->itemToolPrefs().textDistances;
        pixm.imgInfo.lowResType = m_Doc->itemToolPrefs().imageLowResType;
        switch (m_itemType)
        {
                case Polygon:
                        Clip.setPoints(4, static_cast<int>(w / 2), 0, static_cast<int>(w), static_cast<int>(h / 2),
                                                                static_cast<int>(w / 2), static_cast<int>(h), 0, static_cast<int>(h / 2));
                        break;
                default:
                        Clip.setPoints(4, 0, 0, static_cast<int>(w), 0, static_cast<int>(w), static_cast<int>(h), 0, static_cast<int>(h));
                        break;
        }
        OwnPage = m_Doc->currentPage() ? m_Doc->currentPage()->pageNr() : -1;
        oldOwnPage = OwnPage;
        savedOwnPage = OwnPage;
        m_imageVisible = m_Doc->guidesPrefs().showPic;
       
        switch (m_itemType)
        {
                case ImageFrame:
                case OSGFrame:
                case LatexFrame:
                        //We can't determine if this is a latex frame here
                        // because c++'s typeinfos are still saying it's
                        // a plain pageitem
                        // This is fixed in the PageItem_LatexFrame constructor
                        m_itemName = tr("Image");
                        setUPixmap(Um::IImageFrame);
                        break;
                case TextFrame:
                        m_itemName = tr("Text");
                        setUPixmap(Um::ITextFrame);
                        break;
                case Line:
                        m_itemName = tr("Line");
                        setUPixmap(Um::ILine);
                        break;
                case Polygon:
                        m_itemName = tr("Polygon");
                        setUPixmap(Um::IPolygon);
                        break;
                case PolyLine:
                        m_itemName = tr("Polyline");
                        setUPixmap(Um::IPolyline);
                        break;
                case PathText:
                        m_itemName = tr("PathText");
                        setUPixmap(Um::IPathText);
                        break;
                case Symbol:
                        m_itemName = tr("Symbol");
                        setUPixmap(Um::IPolygon);
                        break;
                case Group:
                        m_itemName = tr("Group");
                        setUPixmap(Um::IPolygon);
                        break;
                case RegularPolygon:
                        m_itemName = tr("RegularPolygon");
                        setUPixmap(Um::IPolygon);
                        break;
                case Arc:
                        m_itemName = tr("Arc");
                        setUPixmap(Um::IPolygon);
                        break;
                case Spiral:
                        m_itemName = tr("Spiral");
                        setUPixmap(Um::IPolygon);
                        break;
                case Table:
                        m_itemName = tr("Table");
                        //setUPixmap(Um::IPolygon); // TODO: Fix this.
                        break;
                default:
                        m_itemName = "Item";
                        break;
        }
        m_Doc->TotalItems++;
       
        QString oldName(m_itemName);
        int nameNum = m_Doc->TotalItems;
        m_itemName += tmp.setNum(m_Doc->TotalItems);
        while (m_Doc->itemNameExists(m_itemName))
        {
                ++nameNum;
                m_itemName = oldName + tmp.setNum(nameNum);
        }
       
        uniqueNr = m_Doc->TotalItems;
        setUName(m_itemName);
        m_annotation.setBorderColor(outline);
//      toPixmap = false;
        ImageIntent = Intent_Relative_Colorimetric;
        m_layerID = m_Doc->activeLayer();
        stroke_gradient = VGradient(VGradient::linear);
        stroke_gradient.clearStops();
        if (m_lineColor != CommonStrings::None)
        {
                const ScColor& col = m_Doc->PageColors[m_lineColor];
                QColor qcol = ScColorEngine::getRGBColor(col, m_Doc);
                stroke_gradient.addStop(qcol, 0.0, 0.5, 1.0, m_lineColor, 100);
                stroke_gradient.addStop(qcol, 1.0, 0.5, 1.0, m_lineColor, 100);
        }
        else
        {
                if (m_Doc->itemToolPrefs().shapeLineColor != CommonStrings::None)
                {
                        const ScColor& col = m_Doc->PageColors[m_Doc->itemToolPrefs().shapeLineColor];
                        QColor qcol = ScColorEngine::getRGBColor(col, m_Doc);
                        stroke_gradient.addStop(qcol, 0.0, 0.5, 1.0, m_Doc->itemToolPrefs().shapeLineColor, 100);
                        stroke_gradient.addStop(qcol, 1.0, 0.5, 1.0, m_Doc->itemToolPrefs().shapeLineColor, 100);
                }
                else
                {
                        if (m_fillColor != CommonStrings::None)
                        {
                                const ScColor& col = m_Doc->PageColors[m_fillColor];
                                QColor qcol = ScColorEngine::getRGBColor(col, m_Doc);
                                stroke_gradient.addStop(qcol, 0.0, 0.5, 1.0, m_fillColor, 100);
                                stroke_gradient.addStop(qcol, 1.0, 0.5, 1.0, m_fillColor, 100);
                        }
                        else
                        {
                                if (m_Doc->itemToolPrefs().shapeFillColor != CommonStrings::None)
                                {
                                        const ScColor& col = m_Doc->PageColors[m_Doc->itemToolPrefs().shapeFillColor];
                                        QColor qcol = ScColorEngine::getRGBColor(col, m_Doc);
                                        stroke_gradient.addStop(qcol, 0.0, 0.5, 1.0, m_Doc->itemToolPrefs().shapeFillColor, 100);
                                        stroke_gradient.addStop(qcol, 1.0, 0.5, 1.0, m_Doc->itemToolPrefs().shapeFillColor, 100);
                                }
                                else if (m_Doc->PageColors.contains("Black"))
                                {
                                        const ScColor& col = m_Doc->PageColors["Black"];
                                        QColor qcol = ScColorEngine::getRGBColor(col, m_Doc);
                                        stroke_gradient.addStop(qcol, 0.0, 0.5, 1.0, "Black", 100);
                                        stroke_gradient.addStop(qcol, 1.0, 0.5, 1.0, "Black", 100);
                                }
                        }
                }
        }
        fill_gradient = VGradient(VGradient::linear);
        fill_gradient.clearStops();
        if (m_fillColor != CommonStrings::None)
        {
                const ScColor& col = m_Doc->PageColors[m_fillColor];
                QColor qcol = ScColorEngine::getRGBColor(col, m_Doc);
                fill_gradient.addStop(qcol, 0.0, 0.5, 1.0, m_fillColor, 100);
                fill_gradient.addStop(qcol, 1.0, 0.5, 1.0, m_fillColor, 100);
                GrColorP1 = m_fillColor;
                GrColorP2 = m_fillColor;
                GrColorP3 = m_fillColor;
                GrColorP4 = m_fillColor;
        }
        else
        {
                if (m_Doc->itemToolPrefs().shapeFillColor != CommonStrings::None)
                {
                        const ScColor& col = m_Doc->PageColors[m_Doc->itemToolPrefs().shapeFillColor];
                        QColor qcol = ScColorEngine::getRGBColor(col, m_Doc);
                        fill_gradient.addStop(qcol, 0.0, 0.5, 1.0, m_Doc->itemToolPrefs().shapeFillColor, 100);
                        fill_gradient.addStop(qcol, 1.0, 0.5, 1.0, m_Doc->itemToolPrefs().shapeFillColor, 100);
                        GrColorP1 = m_Doc->itemToolPrefs().shapeFillColor;
                        GrColorP2 = m_Doc->itemToolPrefs().shapeFillColor;
                        GrColorP3 = m_Doc->itemToolPrefs().shapeFillColor;
                        GrColorP4 = m_Doc->itemToolPrefs().shapeFillColor;
                }
                else
                {
                        if (m_lineColor != CommonStrings::None)
                        {
                                const ScColor& col = m_Doc->PageColors[m_lineColor];
                                QColor qcol = ScColorEngine::getRGBColor(col, m_Doc);
                                fill_gradient.addStop(qcol, 0.0, 0.5, 1.0, m_lineColor, 100);
                                fill_gradient.addStop(qcol, 1.0, 0.5, 1.0, m_lineColor, 100);
                                GrColorP1 = m_lineColor;
                                GrColorP2 = m_lineColor;
                                GrColorP3 = m_lineColor;
                                GrColorP4 = m_lineColor;
                        }
                        else
                        {
                                if (m_Doc->itemToolPrefs().shapeLineColor != CommonStrings::None)
                                {
                                        const ScColor& col = m_Doc->PageColors[m_Doc->itemToolPrefs().shapeLineColor];
                                        QColor qcol = ScColorEngine::getRGBColor(col, m_Doc);
                                        fill_gradient.addStop(qcol, 0.0, 0.5, 1.0, m_Doc->itemToolPrefs().shapeLineColor, 100);
                                        fill_gradient.addStop(qcol, 1.0, 0.5, 1.0, m_Doc->itemToolPrefs().shapeLineColor, 100);
                                        GrColorP1 = m_Doc->itemToolPrefs().shapeLineColor;
                                        GrColorP2 = m_Doc->itemToolPrefs().shapeLineColor;
                                        GrColorP3 = m_Doc->itemToolPrefs().shapeLineColor;
                                        GrColorP4 = m_Doc->itemToolPrefs().shapeLineColor;
                                }
                                else if (m_Doc->PageColors.contains("Black"))
                                {
                                        const ScColor& col = m_Doc->PageColors["Black"];
                                        QColor qcol = ScColorEngine::getRGBColor(col, m_Doc);
                                        fill_gradient.addStop(qcol, 0.0, 0.5, 1.0, "Black", 100);
                                        fill_gradient.addStop(qcol, 1.0, 0.5, 1.0, "Black", 100);
                                        GrColorP1 = "Black";
                                        GrColorP2 = "Black";
                                        GrColorP3 = "Black";
                                        GrColorP4 = "Black";
                                }
                        }
                }
        }
        GrMaskEndX = w;
        mask_gradient = VGradient(VGradient::linear);
        mask_gradient.clearStops();
        const ScColor& col = m_Doc->PageColors["Black"];
        QColor qcol = ScColorEngine::getRGBColor(col, m_Doc);
        mask_gradient.addStop(qcol, 0.0, 0.5, 1.0, "Black", 100);
        mask_gradient.addStop(qcol, 1.0, 0.5, 1.0, "Black", 100);

        QList<MeshPoint> mgList;
        MeshPoint mgP;
        meshGradientPatch patch;
        mgP.resetTo(FPoint(0.0, 0.0));
        mgP.transparency = 1.0;
        mgP.shade = 100;
        mgP.colorName = "Black";
        mgP.color = qcol;
        mgList.append(mgP);
        patch.TL = mgP;
        mgP.resetTo(FPoint(m_width / 2.0, 0.0));
        mgList.append(mgP);
        mgP.resetTo(FPoint(m_width, 0.0));
        mgList.append(mgP);
        patch.TR = mgP;
        meshGradientArray.append(mgList);
        mgList.clear();
        mgP.resetTo(FPoint(0.0, m_height / 2.0));
        mgList.append(mgP);
        mgP.resetTo(FPoint(m_width / 2.0, m_height / 2.0));
        mgList.append(mgP);
        mgP.resetTo(FPoint(m_width, m_height / 2.0));
        mgList.append(mgP);
        meshGradientArray.append(mgList);
        mgList.clear();
        mgP.resetTo(FPoint(0.0, m_height));
        mgList.append(mgP);
        patch.BL = mgP;
        mgP.resetTo(FPoint(m_width / 2.0, m_height));
        mgList.append(mgP);
        mgP.resetTo(FPoint(m_width, m_height));
        mgList.append(mgP);
        patch.BR = mgP;
        meshGradientArray.append(mgList);
        meshGradientPatches.append(patch);

        m_firstLineOffset = m_Doc->itemToolPrefs().firstLineOffset;
        m_columns = m_Doc->itemToolPrefs().textColumns;
        m_columnGap = m_Doc->itemToolPrefs().textColumnGap;

        OnMasterPage = m_Doc->currentPage() ? m_Doc->currentPage()->pageName() : QString();
        m_startArrowIndex = m_Doc->itemToolPrefs().lineStartArrow;
        m_endArrowIndex = m_Doc->itemToolPrefs().lineEndArrow;
        effectsInUse.clear();

        //Page Item Attributes
        pageItemAttributes.clear();
        for (const ObjectAttribute& objAttr : qAsConst(m_Doc->itemAttributes()))
        {
                if ((objAttr.autoaddto == "textframes" && m_itemType == TextFrame) ||
                        (objAttr.autoaddto == "imageframes" && m_itemType == ImageFrame))
                {
                        pageItemAttributes.append(objAttr);
                }
        }

        hatchBackground = CommonStrings::None;
        hatchBackgroundQ = QColor();
        hatchForeground = "Black";
        hatchForegroundQ = qcol;
}

PageItem::~PageItem()
{
        if ((isTempFile) && (!Pfile.isEmpty()))
                QFile::remove(Pfile);
        //remove marks

        if (isTextFrame())
        {
                if (!asTextFrame()->isInChain() && itemText.length() > 0)
                {
                        for (int pos = 0; pos < itemText.length(); ++pos)
                        {
                                if (itemText.hasMark(pos))
                                {
                                        Mark* mrk = itemText.mark(pos);
                                        if (!mrk->isType(MARKBullNumType))
                                                m_Doc->eraseMark(mrk);
                                }
                        }
                }
        }
//              if (isWeld())
//                      unWeldFromMaster(true);
//              if (isWelded())
//                      unWeldChild();
}

bool PageItem::isMasterItem() const
{
        if (Parent == nullptr)
                return !OnMasterPage.isEmpty();

        PageItem* parentItem = Parent;
        while (parentItem && parentItem->Parent)
                parentItem = parentItem->Parent;
        return !parentItem->OnMasterPage.isEmpty();
}

bool PageItem::isGroupChild() const
{
        return (dynamic_cast<PageItem_Group*>(Parent) != nullptr);
}

bool PageItem::isTableCell() const
{
        return (dynamic_cast<PageItem_Table*>(Parent) != nullptr);
}

void PageItem::setXPos(const double newXPos, bool drawingOnly)
{
        m_xPos = newXPos;
        if (drawingOnly || m_Doc->isLoading())
                return;
        checkChanges();
}

void PageItem::setYPos(const double newYPos, bool drawingOnly)
{
        m_yPos = newYPos;
        if (drawingOnly || m_Doc->isLoading())
                return;
        checkChanges();
}

void PageItem::setXYPos(const double newXPos, const double newYPos, bool drawingOnly)
{
        m_xPos = newXPos;
        m_yPos = newYPos;
        if (drawingOnly || m_Doc->isLoading())
                return;
        checkChanges();
}

int PageItem::level() const
{
        PageItem* thisItem = const_cast<PageItem*>(this);
        if (isGroupChild())
                return (Parent->asGroupFrame()->groupItemList.indexOf(thisItem) + 1);
        if (!m_Doc)
                return 0;
        QList<PageItem*>* items = OnMasterPage.isEmpty() ? &m_Doc->DocItems : &m_Doc->MasterItems;
        return (items->indexOf(thisItem) + 1);
}

void PageItem::moveBy(const double dX, const double dY, bool drawingOnly)
{
        //qDebug() << "pageitem::moveby" << dX << dY;
        if (dX==0.0 && dY==0.0)
                return;
        invalid = true;
        if (dX != 0.0)
        {
                m_xPos += dX;
                gXpos += dX;
                BoundingX += dX;
        }
        if (dY != 0.0)
        {
                m_yPos += dY;
                gYpos += dY;
                BoundingY += dY;
        }
        if (drawingOnly || m_Doc->isLoading())
                return;
        moveWelded(dX, dY);
        checkChanges();
}

void PageItem::setWidth(double newWidth)
{
        m_width = newWidth;
        updateConstants();
        if (m_Doc->isLoading())
                return;
        checkChanges();
}

void PageItem::setHeight(double newHeight)
{
        m_height = newHeight;
        updateConstants();
        if (m_Doc->isLoading())
                return;
        checkChanges();
}

void PageItem::setWidthHeight(double newWidth, double newHeight, bool drawingOnly)
{
        m_width = newWidth;
        m_height = newHeight;
        updateConstants();
        if (drawingOnly)
                return;
        checkChanges();
}

void PageItem::setWidthHeight(const double newWidth, const double newHeight)
{
        m_width = newWidth;
        m_height = newHeight;
        updateConstants();
        if (m_Doc->isLoading())
                return;
        checkChanges();
}

void PageItem::resizeBy(const double dH, const double dW)
{
        if (dH == 0.0 && dW == 0.0)
                return;
        if (dH != 0.0)
                m_width += dH;
        if (dW != 0.0)
                m_height += dW;
        updateConstants();
        if (m_Doc->isLoading())
                return;
        checkChanges();
}

void PageItem::setRotation(const double newRotation, bool drawingOnly)
{
        double dR = newRotation - m_rotation;
        double oldRot = m_rotation;
        m_rotation = newRotation;
        while (m_rotation < 0.0)
                m_rotation += 360.0;
        while (m_rotation > 360.0)
                m_rotation -= 360.0;
        if (drawingOnly || m_Doc->isLoading())
                return;
        rotateWelded(dR, oldRot);
        checkChanges();
}

void PageItem::rotateBy(const double dR)
{
        if (dR==0.0)
                return;
        m_rotation += dR;
        while (m_rotation < 0.0)
                m_rotation += 360.0;
        while (m_rotation > 360.0)
                m_rotation -= 360.0;
        if (m_Doc->isLoading())
                return;
        checkChanges();
}

void PageItem::setSelected(const bool toSelect)
{
        m_isSelected=toSelect;
}

void PageItem::setImageXScale(const double newImageXScale)
{
        m_imageXScale = newImageXScale;
        if (m_Doc->isLoading())
        {
                oldLocalScX = m_imageXScale;
                return;
        }
        checkChanges();
}

void PageItem::setImageYScale(const double newImageYScale)
{
        m_imageYScale = newImageYScale;
        if (m_Doc->isLoading())
        {
                oldLocalScY = m_imageYScale;
                return;
        }
        checkChanges();
}

void PageItem::setImageXYScale(const double newImageXScale, const double newImageYScale)
{
        m_imageXScale = newImageXScale;
        m_imageYScale = newImageYScale;
        if (m_Doc->isLoading())
        {
                oldLocalScX = m_imageXScale;
                oldLocalScY = m_imageYScale;
                return;
        }
        checkChanges();
}

void PageItem::setImageXOffset(const double newImageXOffset)
{
        m_imageXOffset = newImageXOffset;
        if (m_Doc->isLoading())
        {
                oldLocalX = m_imageXOffset;
                return;
        }
        checkChanges();
}

void PageItem::setImageYOffset(const double newImageYOffset)
{
        m_imageYOffset = newImageYOffset;
        if (m_Doc->isLoading())
        {
                oldLocalY = m_imageYOffset;
                return;
        }
        checkChanges();
}

void PageItem::setImageXYOffset(const double newImageXOffset, const double newImageYOffset)
{
        m_imageXOffset = newImageXOffset;
        m_imageYOffset = newImageYOffset;
        if (m_Doc->isLoading())
        {
                oldLocalX = m_imageXOffset;
                oldLocalY = m_imageYOffset;
                return;
        }
        checkChanges();
}

void PageItem::moveImageXYOffsetBy(const double dX, const double dY)
{
        if (dX==0.0 && dY==0.0)
                return;
        if (dX != 0.0)
                m_imageXOffset += dX;
        if (dY != 0.0)
                m_imageYOffset += dY;
        if (m_Doc->isLoading())
                return;
        checkChanges();
}

void PageItem::setImageRotation(const double newRotation)
{
        if (m_imageRotation == newRotation)
                return;
        if (UndoManager::undoEnabled())
        {
                SimpleState *ss = new SimpleState(Um::Rotate, QString(), Um::IRotate);
                ss->set("IMAGE_ROTATION");
                ss->set("OLD_ROT", m_imageRotation);
                ss->set("NEW_ROT", newRotation);
                undoManager->action(this, ss);
        }
        m_imageRotation = newRotation;
        if (m_Doc->isLoading())
                return;
        checkChanges();
}


/// tests if a character is displayed by this frame
bool PageItem::frameDisplays(int textpos) const
{
        return 0 <= textpos && textpos < signed(m_maxChars) && textpos < itemText.length();
}

PageItem* PageItem::frameOfChar(int textPos)
{
        PageItem* firstFrame = this->firstInChain();
        PageItem* nextFrame = firstFrame;

        while (nextFrame)
        {
                if (nextFrame->invalid)
                        nextFrame->layout();
                if (nextFrame->frameDisplays(textPos))
                        return nextFrame;
                nextFrame = nextFrame->nextInChain();
        }

        return nullptr;
}

//return frame where is text end
PageItem * PageItem::frameTextEnd()
{
        PageItem * LastBox = this;
        if (frameOverflows() && m_nextBox)
        { // text ending in some next frame
                LastBox = m_nextBox;
                while (LastBox != nullptr && !LastBox->frameDisplays(itemText.length()-1))
                        LastBox = LastBox->nextInChain();
        }
        else if (frameUnderflows() && m_backBox)
        { //text ending in some previous frame
                LastBox = m_backBox;
                while (LastBox != nullptr && !LastBox->frameDisplays(itemText.length()-1))
                        LastBox = LastBox->prevInChain();
        }
        return LastBox;
}

/// returns true if text overflows
bool PageItem::frameOverflows() const
{
        // Fix #6991 : "Text overflow" warning when there is a text underflow in fact
        /*return NextBox == nullptr && itemText.length() > static_cast<int>(MaxChars);*/
        return ( m_nextBox == nullptr )
                   && ( firstChar < itemText.length() )
                   // Fix #7766 : scribus.textOverflows() returns 0 if there is no place for the overflow mark
                   /*&& ( firstChar < MaxChars )*/
                   && ( firstChar <= m_maxChars )
                   && ( itemText.length() > m_maxChars );
}

int PageItem::frameOverflowCount() const
{
        if (frameOverflows())
                return itemText.length()-m_maxChars;
        return 0;
}

int PageItem::frameOverflowBlankCount() const
{
        if (frameOverflows())
                return itemText.plainText().right(itemText.length() - m_maxChars).count(QRegularExpression("\\s+"));
        return 0;
}

int PageItem::maxCharsInFrame()
{
        return m_maxChars;
}

/// returns true if text is ending before that frame
bool PageItem::frameUnderflows() const
{
        if (m_backBox == nullptr)
                return false;
        //FIX ME - I have found that condition if frame is empty
        //and has been linked with previous frame
        //if you will find any better solution - fix that function
        return (firstInFrame() > lastInFrame());
}

void PageItem::drawOverflowMarker(ScPainter *p)
{
        qreal sideLength = 10 / qMax(p->zoomFactor(), 1.0);
        qreal offset = 1 / qMax(p->zoomFactor(), 1.0);
        qreal left = m_width - sideLength-offset;// / 2;
        qreal right = left + sideLength;
        qreal top = m_height - sideLength-offset;// * 1.5;
        qreal bottom = top + sideLength;

        QColor color(PrefsManager::instance().appPrefs.displayPrefs.frameNormColor);
        if ((isBookmark) || (m_isAnnotation))
                color = PrefsManager::instance().appPrefs.displayPrefs.frameAnnotationColor;
        if ((m_backBox != nullptr) || (m_nextBox != nullptr))
                color = PrefsManager::instance().appPrefs.displayPrefs.frameLinkColor;
        if (m_Locked)
                color = PrefsManager::instance().appPrefs.displayPrefs.frameLockColor;
        if (m_Doc->m_Selection->containsItem(this))
                color = Qt::red;

        p->save();

        p->setPen(color, 0, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin);
        p->setPenOpacity(1.0);
        p->setBrush(Qt::white);
        p->setBrushOpacity(1.0);
        p->setFillMode(ScPainter::Solid);
        p->drawSharpRect(left, top, sideLength, sideLength);
        p->drawSharpLine(QPointF(left, top), QPointF(right, bottom));
        p->drawSharpLine(QPointF(left, bottom), QPointF(right, top));

        p->restore();
}

int PageItem::firstInFrame() const
{
        return firstChar;
}

int PageItem::lastInFrame() const
{
        return qMin(signed(m_maxChars), itemText.length()) - 1;
}

bool PageItem::canBeLinkedTo(const PageItem* nxt) const
{
        if (this->nextInChain() )
                return false;
        if (!nxt || nxt->prevInChain() )
                return false;
        for (const PageItem* ff = nxt; ff; ff = ff->nextInChain())
        {
                if (ff == this)
                        return false;
        }
        // If object is placed on a master page, it can be linked only to objects placed on same master page
        // Same for objects placed on standard pages : they can only be linked to objects placed on standard pages
        return OnMasterPage == nxt->OnMasterPage;
}

void PageItem::link(PageItem* nxt, bool addPARSEP)
{
        assert( !nextInChain() );
        assert( !nxt->prevInChain() );
        for (PageItem* ff=nxt; ff; ff=ff->nextInChain())
        {
                assert (ff != this);
        }
        // Append only if necessary to avoid the
        // charstyle: access at end of text warning
        bool first = false;
        bool createUndo = addPARSEP;

        if (nxt->prevInChain() == nullptr)
                first = true;
        int textLen = itemText.length();
        if (nxt->itemText.length() > 0)
        {   //case when text will be joined with next frame text
                //do not add PARSEP if first frame has no text or text ends already with PARSEP
                if (addPARSEP && (textLen > 0) && (itemText.text(textLen-1) != SpecialChars::PARSEP))
                        itemText.insertChars(textLen, SpecialChars::PARSEP);
                else
                        addPARSEP = false;
                itemText.append(nxt->itemText);
        }
        else
                addPARSEP = false;
        m_nextBox = nxt;
        nxt->m_backBox = this;
        // update AutoText
        if (isAutoText)
        {
                PageItem* after = nxt;
                while (after)
                {
                        after->isAutoText = true;
                        m_Doc->LastAuto = after;
                        after = after->m_nextBox;
                }
        }
        else if (nxt->isAutoText)
        {
                PageItem* before = this;
                while (before)
                {
                        before->isAutoText = true;
                        m_Doc->FirstAuto = before;
                        before = before->m_backBox;
                }
        }
        invalid = true;
        PageItem* prev = this;
        while (prev->m_backBox && !prev->m_backBox->frameOverflows())
        {
                prev->m_backBox->invalid = true;
                prev = prev->m_backBox;
        }
        while (nxt)
        {
                nxt->itemText = itemText;
                nxt->invalid = true;
                nxt->firstChar = 0;
                nxt = nxt->m_nextBox;
        }
        if (UndoManager::undoEnabled() && createUndo) //addPARESEP is false only if linking is invoked from undo action for unlinkWithText
        {
                ScItemState<QPair<PageItem*, PageItem*> > *is = new ScItemState<QPair<PageItem*, PageItem*> >(Um::LinkTextFrame);
                is->set("LINK_TEXT_FRAME");
                is->set("FIRST", first);
                is->set("JOIN_POS", textLen);
                is->set("ADDPARSEP", addPARSEP);
                is->setItem(qMakePair(this, m_nextBox));
                undoManager->action(this, is);
        }
}

void PageItem::unlink(bool createUndo)
{
        if (m_nextBox)
        {
                PageItem *undoNextBox=m_nextBox;
                // make sure lastInFrame is valid
                layout();
                /*
                //<< CB #6332: Stop the StoryText cut and break and act like other publishing apps
                // move following text to new StoryText
                itemText.select(lastInFrame()+1, itemText.length()-lastInFrame()-1);
                */

                StoryText follow(m_Doc);
                /*
                follow.setDefaultStyle(itemText.defaultStyle());
                follow.insert(0, itemText, true);
                // remove following text from this chain
                itemText.removeSelection();
                //>>
                */

                // update auto pointers
                if (isAutoText)
                {
                        PageItem* before = this;
                        while (before)
                        {
                                before->isAutoText = false;
                                before = before->m_backBox;
                        }
                        m_Doc->FirstAuto = m_nextBox;
                }
                // link following frames to new text
                m_nextBox->firstChar = 0;
                m_nextBox->m_backBox = nullptr;
                while (m_nextBox)
                {
                        m_nextBox->itemText = follow;
                        m_nextBox->invalid = true;
                        m_nextBox->firstChar = 0;
                        m_nextBox = m_nextBox->m_nextBox;
                }
                // NextBox == nullptr now
                m_nextBox = nullptr;
                if (UndoManager::undoEnabled() && createUndo)
                {
                        ScItemState<QPair<PageItem*, PageItem*> > *is = new ScItemState<QPair<PageItem*, PageItem*> >(Um::UnlinkTextFrame);
                        is->set("UNLINK_TEXT_FRAME");
                        is->setItem(qMakePair(this, undoNextBox));
                        undoManager->action(this, is);
                }
        }
}

void PageItem::dropLinks()
{
        // update auto pointers
        if (isAutoText && m_nextBox == nullptr)
                m_Doc->LastAuto = m_backBox;
        if (isAutoText && m_backBox == nullptr)
                m_Doc->FirstAuto = m_nextBox;
        isAutoText = false;

        // leave text in remaining chain
        PageItem* before = m_backBox;
        PageItem* after = m_nextBox;
        if (after == nullptr && before == nullptr)
                return;

        itemText = StoryText(m_Doc);
       
        int afterChar = 0;
        if (before)
        {
                before->m_nextBox = after;
                afterChar = qMin((int) before->m_maxChars, before->itemText.length());
        }
        if (after)
        {
                after->m_backBox = before;
                while (after)
                {
                        after->invalid = true;
                        after->firstChar = afterChar;
                        after = after->m_nextBox;
                }
        }

        if (UndoManager::undoEnabled())
        {
                ScItemState<QPair<PageItem*, PageItem*> > *is = new ScItemState<QPair<PageItem*, PageItem*> >(Um::UnlinkTextFrame);
                is->set("DROP_LINKS");
                is->setItem(qMakePair(m_backBox, m_nextBox));
                undoManager->action(this, is);
        }

        // JG we should set BackBox and NextBox to nullptr at a point
        m_backBox = m_nextBox = nullptr;
}

//unlink selected frame from text chain
//but copy or cut its content from itemText
void PageItem::unlinkWithText()
{
        PageItem* next = m_nextBox;
        PageItem* prev = m_backBox;
        int length = itemText.length();

        if (this->invalid)
                layout();

        //unlink first frame in chain
        if (prev == nullptr)
        {
                if (next->invalid)
                        next->layout();
                if (lastInFrame() < length -1)
                {
                        StoryText content(m_Doc);
                        itemText.select(lastInFrame() + 1, length - (lastInFrame() + 1));
                        content.insert(0, itemText, true);
                        itemText.removeSelection();
                        unlink(false);
                        next->itemText.insert(0, content);
                        next->update();
                }
                else
                {
                        unlink(false);
                }
        }
        else
        {
                if (prev->invalid)
                        prev->layout();
                itemText.select(firstInFrame(), length - firstInFrame());
                StoryText content(m_Doc);
                content.insert(0, itemText, true);
                itemText.removeSelection();
                prev->unlink(false);
                itemText.insert(0, content);
                update();
        }
        if (UndoManager::undoEnabled())
        {
                ScItemState<QPair<PageItem*, PageItem*> > *is = new ScItemState<QPair<PageItem*, PageItem*> >(Um::UnlinkTextFrame);
                is->set("UNLINK_TEXT_FRAME");
                is->set("CUT_TEXT", true);
                is->setItem(qMakePair(prev, next));
                undoManager->action(this, is);
        }
}

/// returns the style at the current charpos
const ParagraphStyle& PageItem::currentStyle() const
{
        int cursorPosition = itemText.cursorPosition();
        if (itemText.hasSelection())
        {
                int firstSelected = itemText.startOfSelection();
                int lastSelected  = qMax(itemText.endOfSelection() - 1, 0);
                cursorPosition = qMax(firstSelected, qMin(cursorPosition, lastSelected));
        }
        // Note: cursor position can be past last characters, don't use frameDisplays() here
        if (cursorPosition >= 0 && cursorPosition <= itemText.length())
                return itemText.paragraphStyle(cursorPosition);
        return itemText.defaultStyle();
}

/// returns the style at the current charpos for changing
ParagraphStyle& PageItem::changeCurrentStyle()
{
        int cursorPosition = itemText.cursorPosition();
        if (itemText.hasSelection())
        {
                int firstSelected = itemText.startOfSelection();
                int lastSelected  = qMax(itemText.endOfSelection() - 1, 0);
                cursorPosition = qMax(firstSelected, qMin(cursorPosition, lastSelected));
        }
        // Note: cursor position can be past last characters, don't use frameDisplays() here
        if (cursorPosition >= 0 && cursorPosition <= itemText.length())
                return const_cast<ParagraphStyle&>(itemText.paragraphStyle(cursorPosition));
        return const_cast<ParagraphStyle&>(itemText.defaultStyle());
}

/// returns the style at the current charpos
const CharStyle& PageItem::currentCharStyle() const
{
        int cursorPosition = itemText.cursorPosition();
        if (itemText.hasSelection())
        {
                int firstSelected = itemText.startOfSelection();
                int lastSelected  = qMax(itemText.endOfSelection() - 1, 0);
                cursorPosition = qMax(firstSelected, qMin(cursorPosition, lastSelected));
        }
        // Note: cursor position can be past last characters, don't use frameDisplays() here
        if (cursorPosition >= 0 && cursorPosition <= itemText.length())
                return itemText.charStyle(cursorPosition);
        return itemText.defaultStyle().charStyle();
}

void PageItem::currentTextProps(ParagraphStyle& parStyle) const
{
        const ParagraphStyle& curStyle = this->currentStyle();
        parStyle.setContext(curStyle.context());
        parStyle = curStyle;

        int position = itemText.cursorPosition();
        if (itemText.hasSelection())
                position = qMin(qMax(itemText.endOfSelection() - 1, 0), qMax(position, itemText.startOfSelection()));

        // Note: cursor position can be past last characters, don't use frameDisplays() here
        if (position >= 0 && position <= itemText.length())
        {
                // Do not use setStyle here otherwise char style properties explicitly
                // set at paragraph level without using styles might get lost
                parStyle.charStyle().applyCharStyle( itemText.charStyle(position) );
        }
        else
                parStyle.charStyle().setStyle( itemText.defaultStyle().charStyle() );
}

void PageItem::setTextToFrameDistLeft(double newLeft)
{
        if (m_textDistanceMargins.left() == newLeft)
                return;
        if (UndoManager::undoEnabled())
        {
                SimpleState *ss = new SimpleState(Um::TextFrameDist, QString(), Um::ITextFrame);
                ss->set("LEFT_TEXTFRAMEDIST");
                ss->set("OLD_DIST", m_textDistanceMargins.left());
                ss->set("NEW_DIST", newLeft);
                undoManager->action(this, ss);
        }
        m_textDistanceMargins.setLeft(newLeft);
        //emit textToFrameDistances(Extra, TExtra, BExtra, RExtra);
}

void PageItem::setTextToFrameDistRight(double newRight)
{
        if (m_textDistanceMargins.right() == newRight)
                return;
        if (UndoManager::undoEnabled())
        {
                SimpleState *ss = new SimpleState(Um::TextFrameDist, QString(), Um::ITextFrame);
                ss->set("RIGHT_TEXTFRAMEDIST");
                ss->set("OLD_DIST", m_textDistanceMargins.right());
                ss->set("NEW_DIST", newRight);
                undoManager->action(this, ss);
        }
        m_textDistanceMargins.setRight(newRight);
        //emit textToFrameDistances(Extra, TExtra, BExtra, RExtra);
}

void PageItem::setTextToFrameDistTop(double newTop)
{
        if (m_textDistanceMargins.top() == newTop)
                return;
        if (UndoManager::undoEnabled())
        {
                SimpleState *ss = new SimpleState(Um::TextFrameDist, QString(), Um::ITextFrame);
                ss->set("TOP_TEXTFRAMEDIST");
                ss->set("OLD_DIST", m_textDistanceMargins.top());
                ss->set("NEW_DIST", newTop);
                undoManager->action(this, ss);
        }
        m_textDistanceMargins.setTop(newTop);
        //emit textToFrameDistances(Extra, TExtra, BExtra, RExtra);
}

void PageItem::setTextToFrameDistBottom(double newBottom)
{
        if (m_textDistanceMargins.bottom() == newBottom)
                return;
        if (UndoManager::undoEnabled())
        {
                SimpleState *ss = new SimpleState(Um::TextFrameDist, QString(), Um::ITextFrame);
                ss->set("BOTTOM_TEXTFRAMEDIST");
                ss->set("OLD_DIST", m_textDistanceMargins.bottom());
                ss->set("NEW_DIST", newBottom);
                undoManager->action(this, ss);
        }
        m_textDistanceMargins.setBottom(newBottom);
        //emit textToFrameDistances(Extra, TExtra, BExtra, RExtra);
}

void PageItem::setTextToFrameDist(double newLeft, double newRight, double newTop, double newBottom)
{
        UndoTransaction activeTransaction;
        if (UndoManager::undoEnabled())
                activeTransaction = undoManager->beginTransaction(Um::TextFrame, Um::IDocument, Um::TextFrameDist, QString(), Um::ITextFrame);
        setTextToFrameDistLeft(newLeft);
        setTextToFrameDistRight(newRight);
        setTextToFrameDistTop(newTop);
        setTextToFrameDistBottom(newBottom);
        if (activeTransaction)
                activeTransaction.commit();
        //emit textToFrameDistances(Extra, TExtra, BExtra, RExtra);
}

double PageItem::gridOffset() const
{
        return m_Doc->guidesPrefs().offsetBaselineGrid;
}
double PageItem::gridDistance() const
{
        return m_Doc->guidesPrefs().valueBaselineGrid;
}

void PageItem::setGridOffset(double) { } // FIXME
void PageItem::setGridDistance(double) { } // FIXME

void PageItem::setColumns(int newColumnCount)
{
        if (m_columns==newColumnCount)
                return;
        if (UndoManager::undoEnabled())
        {
                SimpleState *ss = new SimpleState(Um::Columns, QString(), Um::IBorder);
                ss->set("COLUMNS");
                ss->set("OLD_COLUMNS", m_columns);
                ss->set("NEW_COLUMNS", newColumnCount);
                undoManager->action(this, ss);
        }
        m_columns = qMax(1, newColumnCount);
}

void PageItem::setColumnGap(double newColumnGap)
{
        if (m_columnGap==newColumnGap)
                return;
        if (UndoManager::undoEnabled())
        {
                SimpleState *ss = new SimpleState(Um::Columns, QString(), Um::IBorder);
                ss->set("COLUMNSGAP");
                ss->set("OLD_COLUMNS", m_columnGap);
                ss->set("NEW_COLUMNS", newColumnGap);
                undoManager->action(this, ss);
        }
        m_columnGap = newColumnGap;
}

int PageItem::verticalAlignment()
{
        return verticalAlign;
}

void PageItem::setVerticalAlignment(int val)
{
        if (val == verticalAlign)
                return;
        if (UndoManager::undoEnabled())
        {
                SimpleState *ss = new SimpleState(Um::AlignText, QString(), Um::ITextFrame);
                ss->set("VERTICAL_ALIGN");
                ss->set("OLD_VERTALIGN", verticalAlign);
                ss->set("NEW_VERTALIGN", val);
                undoManager->action(this, ss);
        }
        verticalAlign = val;
}

void PageItem::setCornerRadius(double newRadius)
{
        if (m_roundedCornerRadius == newRadius)
                return;
        if (UndoManager::undoEnabled())
        {
                SimpleState *state = new SimpleState(Um::RoundCorner, QString(), Um::IBorder);
                state->set("CORNER_RADIUS");
                state->set("OLD_RADIUS", m_roundedCornerRadius);
                state->set("NEW_RADIUS", newRadius);
                undoManager->action(this,state);
        }
        m_roundedCornerRadius=newRadius;
        //emit cornerRadius(RadRect);
}



/** Paints the item.
    CHANGE: cullingArea is in doc coordinates!
 */

void PageItem::DrawObj(ScPainter *p, QRectF cullingArea)
{
        // #12698: Prevent drawing of line items
        /*if (PoLine.isEmpty())
                return;*/

        if (cullingArea.isNull())
        {
                cullingArea = QRectF(QPointF(m_Doc->minCanvasCoordinate.x(), m_Doc->minCanvasCoordinate.y()),
                                                         QPointF(m_Doc->maxCanvasCoordinate.x(), m_Doc->maxCanvasCoordinate.y())).toAlignedRect();
        }

        no_fill = false;
        no_stroke = false;
        DrawObj_Pre(p);
        if (m_Doc->layerOutline(m_layerID))
        {
                if ((itemType() == TextFrame || itemType() == ImageFrame || itemType() == PathText || itemType() == Line || itemType() == PolyLine || itemType() == Group || itemType() == Symbol))
                        DrawObj_Item(p, cullingArea);
        }
        else
        {
                DrawObj_Item(p, cullingArea);
        }
        DrawObj_Post(p);
}

void PageItem::DrawObj_Pre(ScPainter *p)
{
        p->save();
        double lwCorr = m_lineWidth;
        double sc = p->zoomFactor();
        if ((m_lineWidth * sc) < 1)
                lwCorr = 0;
        if (!isEmbedded)
                p->translate(m_xPos, m_yPos);
        p->rotate(m_rotation);

        if (m_Doc->layerOutline(m_layerID))
        {
                p->setPen(m_Doc->layerMarker(m_layerID), 0, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin);
                p->setFillMode(ScPainter::None);
                p->setBrushOpacity(1.0);
                p->setPenOpacity(1.0);
                return;
        }

        if ((hasSoftShadow()) && (m_Doc->appMode != modeEdit))
                DrawSoftShadow(p);
        if (isGroup())
                return;
        p->setBlendModeFill(fillBlendmode());
        p->setLineWidth(lwCorr);
        if (GrType != 0)
        {
                if (GrType == Gradient_Pattern)
                {
                        ScPattern *pattern = m_Doc->checkedPattern(m_patternName);
                        if (!pattern)
                        {
                                p->fill_gradient = VGradient(VGradient::linear);
                                p->fill_gradient.setRepeatMethod(GrExtend);
                                if (fillColor() != CommonStrings::None)
                                {
                                        p->setBrush(m_fillQColor);
                                        p->setFillMode(ScPainter::Solid);
                                }
                                else
                                {
                                        no_fill = true;
                                        p->setFillMode(ScPainter::None);
                                }
                                if ((!m_patternName.isEmpty()) && (!m_Doc->docPatterns.contains(m_patternName)))
                                {
                                        GrType = 0;
                                        m_patternName = "";
                                }
                        }
                        else
                        {
                                p->setPattern(pattern, patternScaleX, patternScaleY, patternOffsetX, patternOffsetY, patternRotation, patternSkewX, patternSkewY, patternMirrorX, patternMirrorY);
                                p->setFillMode(ScPainter::Pattern);
                        }
                }
                else
                {
                        if (GrType == Gradient_4Colors)
                        {
                                p->setFillMode(ScPainter::Gradient);
                                FPoint pG1 = FPoint(0, 0);
                                FPoint pG2 = FPoint(width(), 0);
                                FPoint pG3 = FPoint(width(), height());
                                FPoint pG4 = FPoint(0, height());
                                p->set4ColorGeometry(pG1, pG2, pG3, pG4, GrControl1, GrControl2, GrControl3, GrControl4);
                                p->set4ColorColors(m_grQColorP1, m_grQColorP2, m_grQColorP3, m_grQColorP4);
                        }
                        else if (GrType == Gradient_Hatch)
                        {
                                if (fillColor() != CommonStrings::None)
                                        p->setBrush(m_fillQColor);
                                p->setFillMode(ScPainter::Hatch);
                                p->setHatchParameters(hatchType, hatchDistance, hatchAngle, hatchUseBackground, hatchBackgroundQ, hatchForegroundQ, width(), height());
                        }
                        else
                        {
                                if ((!m_gradientName.isEmpty()) && (!m_Doc->docGradients.contains(m_gradientName)))
                                        m_gradientName = "";
                                if (!(m_gradientName.isEmpty()) && (m_Doc->docGradients.contains(m_gradientName)))
                                        fill_gradient = m_Doc->docGradients[m_gradientName];
                                if ((fill_gradient.stops() < 2) && (GrType < Gradient_4Colors)) // fall back to solid filling if there are not enough colorstops in the gradient.
                                {
                                        if (fillColor() != CommonStrings::None)
                                        {
                                                p->setBrush(m_fillQColor);
                                                p->setFillMode(ScPainter::Solid);
                                        }
                                        else
                                        {
                                                no_fill = true;
                                                p->setFillMode(ScPainter::None);
                                        }
                                }
                                else
                                {
                                        p->setFillMode(ScPainter::Gradient);
                                        p->fill_gradient = fill_gradient;
                                        p->fill_gradient.setRepeatMethod(GrExtend);
                                        switch (GrType)
                                        {
                                                case Gradient_LinearLegacy1:
                                                case Gradient_LinearLegacy2:
                                                case Gradient_LinearLegacy3:
                                                case Gradient_LinearLegacy4:
                                                case Gradient_Linear:
                                                        p->setGradient(VGradient::linear, FPoint(GrStartX, GrStartY), FPoint(GrEndX, GrEndY), FPoint(GrStartX, GrStartY), GrScale, GrSkew);
                                                        break;
                                                case Gradient_RadialLegacy5:
                                                case Gradient_Radial:
                                                        p->setGradient(VGradient::radial, FPoint(GrStartX, GrStartY), FPoint(GrEndX, GrEndY), FPoint(GrFocalX, GrFocalY), GrScale, GrSkew);
                                                        break;
                                                case Gradient_Diamond:
                                                        p->setFillMode(ScPainter::Gradient);
                                                        p->setDiamondGeometry(FPoint(0, 0), FPoint(width(), 0), FPoint(width(), height()), FPoint(0, height()), GrControl1, GrControl2, GrControl3, GrControl4, GrControl5);
                                                        break;
                                                case Gradient_Mesh:
                                                case Gradient_Conical:
                                                        p->setFillMode(ScPainter::Gradient);
                                                        p->setMeshGradient(FPoint(0, 0), FPoint(width(), 0), FPoint(width(), height()), FPoint(0, height()), meshGradientArray);
                                                        break;
                                                case Gradient_PatchMesh:
                                                        p->setFillMode(ScPainter::Gradient);
                                                        p->setMeshGradient(FPoint(0, 0), FPoint(width(), 0), FPoint(width(), height()), FPoint(0, height()), meshGradientPatches);
                                                        break;
                                        }
                                }
                        }
                }
        }
        else
        {
                p->fill_gradient = VGradient(VGradient::linear);
                if (fillColor() != CommonStrings::None)
                {
                        p->setBrush(m_fillQColor);
                        p->setFillMode(ScPainter::Solid);
                }
                else
                {
                        no_fill = true;
                        p->setFillMode(ScPainter::None);
                }
        }
        if ((lineColor() != CommonStrings::None) || (!patternStrokeVal.isEmpty()) || (GrTypeStroke > 0))
        {
                p->setPen(m_strokeQColor, lwCorr, PLineArt, PLineEnd, PLineJoin);
                if (DashValues.count() != 0)
                        p->setDash(DashValues, DashOffset);
        }
        else
                p->setLineWidth(0);
        p->setBrushOpacity(1.0 - fillTransparency());
        p->setPenOpacity(1.0 - lineTransparency());
        p->setFillRule(fillRule);
        if ((GrMask == GradMask_Linear) || (GrMask == GradMask_Radial) || (GrMask == GradMask_LinearLumAlpha) || (GrMask == GradMask_RadialLumAlpha))
        {
                if ((GrMask == GradMask_Linear) || (GrMask == GradMask_Radial))
                        p->setMaskMode(1);
                else
                        p->setMaskMode(3);
                if ((!gradientMaskVal.isEmpty()) && (!m_Doc->docGradients.contains(gradientMaskVal)))
                        gradientMaskVal = "";
                if (!(gradientMaskVal.isEmpty()) && (m_Doc->docGradients.contains(gradientMaskVal)))
                        mask_gradient = m_Doc->docGradients[gradientMaskVal];
                p->mask_gradient = mask_gradient;
                if ((GrMask == GradMask_Linear) || (GrMask == GradMask_LinearLumAlpha))
                        p->setGradientMask(VGradient::linear, FPoint(GrMaskStartX, GrMaskStartY), FPoint(GrMaskEndX, GrMaskEndY), FPoint(GrMaskStartX, GrMaskStartY), GrMaskScale, GrMaskSkew);
                else
                        p->setGradientMask(VGradient::radial, FPoint(GrMaskStartX, GrMaskStartY), FPoint(GrMaskEndX, GrMaskEndY), FPoint(GrMaskFocalX, GrMaskFocalY), GrMaskScale, GrMaskSkew);
        }
        else if ((GrMask == GradMask_Pattern) || (GrMask == GradMask_PatternLumAlpha) || (GrMask == GradMask_PatternLumAlphaInverted) || (GrMask == GradMask_PatternInverted))
        {
                ScPattern *patternMask = m_Doc->checkedPattern(patternMaskVal);
                if (patternMask)
                {
                        p->setPatternMask(patternMask, patternMaskScaleX, patternMaskScaleY, patternMaskOffsetX, patternMaskOffsetY, patternMaskRotation, patternMaskSkewX, patternMaskSkewY, patternMaskMirrorX, patternMaskMirrorY);
                        if (GrMask == GradMask_Pattern)
                                p->setMaskMode(2);
                        else if (GrMask == GradMask_PatternLumAlpha)
                                p->setMaskMode(4);
                        else if (GrMask == GradMask_PatternLumAlphaInverted)
                                p->setMaskMode(5);
                        else
                                p->setMaskMode(6);
                }
                else
                {
                        p->setMaskMode(0);
                }
        }
        else
                p->setMaskMode(0);
}

void PageItem::DrawObj_Post(ScPainter *p)
{
        bool doStroke=true;
        double lwCorr = m_lineWidth;
        if ((m_lineWidth * p->zoomFactor()) < 1)
                lwCorr = 0;
        if (m_Doc->layerOutline(m_layerID))
        {
                if (itemType()!=Line)
                {
                        p->setPen(m_Doc->layerMarker(m_layerID), 0, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin);
                        p->setFillMode(ScPainter::None);
                        p->setBrushOpacity(1.0);
                        p->setPenOpacity(1.0);
                        if (itemType() == PolyLine)
                                p->setupPolygon(&PoLine, false);
                        else if (itemType() == PathText)
                        {
                                if (PoShow)
                                        p->setupPolygon(&PoLine, false);
                                else
                                        doStroke = false;
                        }
                        else
                                p->setupPolygon(&PoLine);
                        if (doStroke)
                                p->strokePath();
                        if (itemType() == ImageFrame)
                        {
                                if (!imageClip.empty())
                                {
                                        p->setupPolygon(&imageClip);
                                        p->strokePath();
                                }
                        }
                }
        }
        else
        {
                if (!isGroup())
                {
                        p->setBlendModeFill(0);
                        p->setMaskMode(0);
                        // TODO: Investigate whether itemType() == Table should really be here. I got artifacts without it so keeping it here for now. /estan
                        if (itemType() == PathText || itemType() == PolyLine || itemType() == Spiral || itemType() == Line || itemType() == Symbol || itemType() == Group || itemType() == Table)
                                doStroke=false;
                        if ((doStroke) && (!m_Doc->RePos))
                        {
                                p->setBlendModeStroke(lineBlendmode());
                                p->setPenOpacity(1.0 - lineTransparency());
                                if ((lineColor() != CommonStrings::None) || (!patternStrokeVal.isEmpty()) || (GrTypeStroke > 0))
                                {
                                        p->setPen(m_strokeQColor, lwCorr, PLineArt, PLineEnd, PLineJoin);
                                        if (DashValues.count() != 0)
                                                p->setDash(DashValues, DashOffset);
                                }
                                else
                                        p->setLineWidth(0);
                                if ((itemType() == LatexFrame) || (itemType() == ImageFrame) || (itemType() == OSGFrame))
                                        p->setupPolygon(&PoLine);
                                if (NamedLStyle.isEmpty())
                                {
                                        ScPattern *strokePattern = m_Doc->checkedPattern(patternStrokeVal);
                                        if (strokePattern)
                                        {
                                                if (patternStrokePath)
                                                {
                                                        QPainterPath guidePath = PoLine.toQPainterPath(false);
                                                        DrawStrokePattern(p, guidePath);
                                                }
                                                else
                                                {
                                                        p->setPattern(strokePattern, patternStrokeScaleX, patternStrokeScaleY, patternStrokeOffsetX, patternStrokeOffsetY, patternStrokeRotation, patternStrokeSkewX, patternStrokeSkewY, patternStrokeMirrorX, patternStrokeMirrorY);
                                                        p->setStrokeMode(ScPainter::Pattern);
                                                        p->strokePath();
                                                }
                                        }
                                        else if (GrTypeStroke > 0)
                                        {
                                                if ((!gradientStrokeVal.isEmpty()) && (!m_Doc->docGradients.contains(gradientStrokeVal)))
                                                        gradientStrokeVal.clear();
                                                if (!(gradientStrokeVal.isEmpty()) && (m_Doc->docGradients.contains(gradientStrokeVal)))
                                                        stroke_gradient = m_Doc->docGradients[gradientStrokeVal];
                                                if (stroke_gradient.stops() < 2) // fall back to solid stroking if there are not enough colorstops in the gradient.
                                                {
                                                        if (lineColor() != CommonStrings::None)
                                                        {
                                                                p->setBrush(m_strokeQColor);
                                                                p->setStrokeMode(ScPainter::Solid);
                                                        }
                                                        else
                                                        {
                                                                no_stroke = true;
                                                                p->setStrokeMode(ScPainter::None);
                                                        }
                                                }
                                                else
                                                {
                                                        p->setStrokeMode(ScPainter::Gradient);
                                                        p->stroke_gradient = stroke_gradient;
                                                        p->stroke_gradient.setRepeatMethod(GrStrokeExtend);
                                                        if (GrTypeStroke == Gradient_Linear)
                                                                p->setGradient(VGradient::linear, FPoint(GrStrokeStartX, GrStrokeStartY), FPoint(GrStrokeEndX, GrStrokeEndY), FPoint(GrStrokeStartX, GrStrokeStartY), GrStrokeScale, GrStrokeSkew);
                                                        else
                                                                p->setGradient(VGradient::radial, FPoint(GrStrokeStartX, GrStrokeStartY), FPoint(GrStrokeEndX, GrStrokeEndY), FPoint(GrStrokeFocalX, GrStrokeFocalY), GrStrokeScale, GrStrokeSkew);
                                                }
                                                p->strokePath();
                                        }
                                        else if (lineColor() != CommonStrings::None)
                                        {
                                                p->setStrokeMode(ScPainter::Solid);
                                                p->setPen(m_strokeQColor, lwCorr, PLineArt, PLineEnd, PLineJoin);
                                                if (DashValues.count() != 0)
                                                        p->setDash(DashValues, DashOffset);
                                                p->strokePath();
                                        }
                                        else
                                                no_stroke = true;
                                        if (lineTransparency() > 0.9)
                                                no_stroke = true;
                                }
                                else
                                {
                                        p->setStrokeMode(ScPainter::Solid);
                                        multiLine ml = m_Doc->docLineStyles[NamedLStyle];
                                        QColor tmp;
                                        for (int it = ml.size()-1; it > -1; it--)
                                        {
                                                struct SingleLine& sl = ml[it];
                                                // Qt4 if ((!sl.Color != CommonStrings::None) && (sl.Width != 0))
                                                if (sl.Color != CommonStrings::None) // && (sl.Width != 0))
                                                {
                                                        SetQColor(&tmp, sl.Color, sl.Shade);
                                                        p->setPen(tmp, sl.Width, static_cast<Qt::PenStyle>(sl.Dash), static_cast<Qt::PenCapStyle>(sl.LineEnd), static_cast<Qt::PenJoinStyle>(sl.LineJoin));
                                                        p->strokePath();
                                                }
                                        }
                                }
                                p->setBlendModeStroke(0);
                        }
                }
        }
        p->setFillMode(ScPainter::Solid);
        p->setBlendModeFill(0);
        p->setStrokeMode(ScPainter::Solid);
        p->setBlendModeStroke(0);
        p->restore();
}

void PageItem::DrawObj_Decoration(ScPainter *p)
{
        p->save();
//      p->setAntialiasing(false);
        if (!isEmbedded)
                p->translate(m_xPos, m_yPos);
        p->rotate(m_rotation);
        if ((!isEmbedded) && (!m_Doc->RePos))
        {
                double scpInv = 0;
                if (!isGroup())
                {
                        if ((drawFrame()) && (m_Doc->guidesPrefs().framesShown) && ((itemType() == ImageFrame) || (itemType() == LatexFrame) || (itemType() == OSGFrame) || (itemType() == PathText)) && (no_stroke))
                        {
                                p->setPen(PrefsManager::instance().appPrefs.displayPrefs.frameNormColor, scpInv, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin);
                                if ((isBookmark) || (m_isAnnotation))
                                        p->setPen(PrefsManager::instance().appPrefs.displayPrefs.frameAnnotationColor, scpInv, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin);
                                if ((m_backBox != nullptr) || (m_nextBox != nullptr))
                                        p->setPen(PrefsManager::instance().appPrefs.displayPrefs.frameLinkColor, scpInv, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin);
                                if (m_Locked)
                                        p->setPen(PrefsManager::instance().appPrefs.displayPrefs.frameLockColor, scpInv, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin);
                                p->setFillMode(ScPainter::None);
                                if (itemType() == PathText)
                                {
                                        if (Clip.count() != 0)
                                        {
                                                FPointArray tclip;
                                                FPoint np = FPoint(Clip.point(0));
                                                tclip.resize(2);
                                                tclip.setPoint(0, np);
                                                tclip.setPoint(1, np);
                                                for (int a = 1; a < Clip.size(); ++a)
                                                {
                                                        np = FPoint(Clip.point(a));
                                                        tclip.putPoints(tclip.size(), 4, np.x(), np.y(), np.x(), np.y(), np.x(), np.y(), np.x(), np.y());
                                                }
                                                np = FPoint(Clip.point(0));
                                                tclip.putPoints(tclip.size(), 2, np.x(), np.y(), np.x(), np.y());
                                                p->setupPolygon(&tclip);
                                        }
                                }
                                else
                                        p->setupSharpPolygon(&PoLine);
                                p->strokePath();
                        }
                }
                if ((m_Doc->guidesPrefs().framesShown) && textFlowUsesContourLine() && (!ContourLine.empty()))
                {
                        p->setPen(Qt::darkGray, 0, Qt::DotLine, Qt::FlatCap, Qt::MiterJoin);
                        p->setupSharpPolygon(&ContourLine);
                        p->strokePath();
                }
                if (itemType() == ImageFrame)
                {
                        double minres = m_Doc->checkerProfiles()[m_Doc->curCheckProfile()].minResolution;
                        double maxres = m_Doc->checkerProfiles()[m_Doc->curCheckProfile()].maxResolution;
                        bool checkres = m_Doc->checkerProfiles()[m_Doc->curCheckProfile()].checkResolution;
                        if  ((((72.0 / imageXScale()) < minres)
                                || ((72.0 / imageYScale()) < minres)
                                || ((72.0 / imageXScale()) > maxres)
                                || ((72.0 / imageYScale()) > maxres))
                                && (isRaster) && (checkres) && (!m_Doc->drawAsPreview) && (PrefsManager::instance().appPrefs.displayPrefs.showVerifierWarningsOnCanvas))
                        {
                                double ofx = m_width - 22.0;
                                double ofy = m_height - 22.0;
                                if ((m_width > 40) && (m_height > 40))
                                {
                                        p->save();
                                        p->translate(ofx, ofy);
                                        QImage ico = IconManager::instance().loadPixmap("22/dialog-warning.png").toImage();
                                        p->drawImage(&ico);
                                        p->restore();
                                }
                        }
                }
                if ((m_Doc->guidesPrefs().layerMarkersShown) &&
                        (m_Doc->layerCount() > 1) &&
                        (!m_Doc->layerOutline(m_layerID)) &&
                        (!isGroupChild()) &&
                        (!m_Doc->drawAsPreview))
                {
                        p->setPen(Qt::black, 0, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin);
                        p->setPenOpacity(1.0);
                        p->setBrush(m_Doc->layerMarker(m_layerID));
                        p->setBrushOpacity(1.0);
                        p->setFillMode(ScPainter::Solid);
                        double ofwh = 10;
                        double ofx = m_width - ofwh/2;
                        double ofy = m_height - ofwh*3;
                        p->drawSharpRect(ofx, ofy, ofwh, ofwh);
                }
                if (no_fill && no_stroke && m_Doc->guidesPrefs().framesShown)
                {
                        p->setPen(PrefsManager::instance().appPrefs.displayPrefs.frameNormColor, scpInv, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin);
                        if (m_Locked)
                                p->setPen(PrefsManager::instance().appPrefs.displayPrefs.frameLockColor, scpInv, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin);
                        p->setFillMode(ScPainter::None);
                        p->drawSharpRect(0, 0, m_width, m_height);
                        no_fill = false;
                        no_stroke = false;
                }
                //CB disabled for now
                //if (m_Doc->m_Selection->findItem(this)!=-1)
                //      drawLockedMarker(p);
        }
        FrameOnly = false;
//      p->setAntialiasing(true);
        p->restore();
}

void PageItem::DrawObj_Embedded(ScPainter *p, QRectF cullingArea, const CharStyle& style, PageItem* cembedded)
{
        if (!cembedded)
                return;
        QList<PageItem*> emG;
        emG.clear();
        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->m_xPos = embedded->gXpos;
                embedded->m_yPos = (embedded->gHeight * (style.scaleV() / 1000.0)) + embedded->gYpos;
                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->m_yPos -= embedded->gHeight * (style.baselineOffset() / 1000.0);
                }
                p->scale(style.scaleH() / 1000.0, style.scaleV() / 1000.0);
                embedded->invalid = true;
                double pws = embedded->m_lineWidth;
                embedded->DrawObj_Pre(p);
                switch (embedded->itemType())
                {
                        case ImageFrame:
                        case TextFrame:
                        case LatexFrame:
                        case OSGFrame:
                        case Polygon:
                        case PathText:
                        case Symbol:
                        case Group:
                        case RegularPolygon:
                        case Arc:
                        case Table:
                                embedded->DrawObj_Item(p, cullingArea);
                                break;
                        case Line:
                        case PolyLine:
                        case Spiral:
                                embedded->m_lineWidth = pws * qMin(style.scaleH() / 1000.0, style.scaleV() / 1000.0);
                                embedded->DrawObj_Item(p, cullingArea);
                                break;
                        default:
                                break;
                }
                embedded->m_lineWidth = pws * qMin(style.scaleH() / 1000.0, style.scaleV() / 1000.0);
                embedded->DrawObj_Post(p);
                embedded->m_xPos = x;
                embedded->m_yPos = y;
                p->restore();
                embedded->m_lineWidth = pws;
        }
        if (m_Doc->guidesPrefs().framesShown)
        {
                p->save();
                p->translate(0, -(cembedded->m_height * (style.scaleV() / 1000.0)));
                if (style.baselineOffset() != 0)
                        p->translate(0, -cembedded->m_height * (style.baselineOffset() / 1000.0));
                p->scale(style.scaleH() / 1000.0, style.scaleV() / 1000.0);
                p->setPen(PrefsManager::instance().appPrefs.displayPrefs.frameNormColor, 0, Qt::DotLine, Qt::FlatCap, Qt::MiterJoin);
                p->setFillMode(ScPainter::None);
                p->drawSharpRect(0, 0, cembedded->m_width, cembedded->m_height);
                p->restore();
        }
}

void PageItem::DrawStrokePattern(ScPainter *p, QPainterPath &path)
{
        ScPattern pat = m_Doc->docPatterns[patternStrokeVal];
        double pLen = path.length() - ((pat.width / 2.0) * (patternStrokeScaleX / 100.0));
        double adv = pat.width * patternStrokeScaleX / 100.0 * patternStrokeSpace;
        double xpos = patternStrokeOffsetX * patternStrokeScaleX / 100.0;
        while (xpos < pLen)
        {
                double currPerc = path.percentAtLength(xpos);
                double currAngle = path.angleAtPercent(currPerc);
                if (currAngle <= 180.0)
                        currAngle *= -1.0;
                else
                        currAngle = 360.0 - currAngle;
                QPointF currPoint = path.pointAtPercent(currPerc);
                p->save();
                p->translate(currPoint.x(), currPoint.y());
                p->rotate(currAngle);
                QTransform savWM = p->worldMatrix();
                QTransform trans;
                trans.translate(0.0, patternStrokeOffsetY);
                trans.rotate(patternStrokeRotation);
                trans.shear(-patternStrokeSkewX, patternStrokeSkewY);
                trans.scale(patternStrokeScaleX / 100.0, patternStrokeScaleY / 100.0);
                trans.translate(-pat.width / 2.0, -pat.height / 2.0);
                if (patternStrokeMirrorX)
                {
                        trans.translate(pat.width, 0);
                        trans.scale(-1, 1);
                }
                if (patternStrokeMirrorY)
                {
                        trans.translate(0, pat.height);
                        trans.scale(1, -1);
                }
                trans *= savWM;
                p->setWorldMatrix(trans);
                for (int em = 0; em < pat.items.count(); ++em)
                {
                        PageItem* embedded = pat.items.at(em);
                        p->save();
                        p->translate(embedded->gXpos, embedded->gYpos);
                        embedded->isEmbedded = true;
                        embedded->invalid = true;
                        embedded->DrawObj(p, QRectF());
                        embedded->isEmbedded = false;
                        p->restore();
                }
                p->setWorldMatrix(savWM);
                xpos += adv;
                p->restore();
        }
        p->newPath();
}

void PageItem::DrawSoftShadow(ScPainter *p)
{
        if (m_softShadowColor == CommonStrings::None)
                return;
        double lwCorr = m_lineWidth;
        double sc = p->zoomFactor();
        if ((m_lineWidth * sc) < 1)
                lwCorr = 0;
        const ScColor& col = m_Doc->PageColors[m_softShadowColor];
        QColor tmp = ScColorEngine::getShadeColorProof(col, m_Doc, m_softShadowShade);
        if (m_Doc->viewAsPreview)
        {
                VisionDefectColor defect;
                tmp = defect.convertDefect(tmp, m_Doc->previewVisual);
        }
        p->save();
        if (m_softShadowHasObjectTransparency)
                p->beginLayer(1.0 - fillTransparency(), m_softShadowBlendMode);
        else
                p->beginLayer(1.0 - m_softShadowOpacity, m_softShadowBlendMode);
        if (!hasFill())
        {
                double xOffset = isEmbedded ? m_softShadowXOffset : (m_softShadowXOffset - m_xPos);
                double yOffset = isEmbedded ? m_softShadowYOffset : (m_softShadowYOffset - m_yPos);
                double fillTrans_Old = fillTransparency();
                double lineTrans_Old = lineTransparency();
                bool   hasSoftShadow_Old = hasSoftShadow();
                double rotation_Old = m_rotation;
                m_fillTransparency = 0.0;
                m_lineTransparency = 0.0;
                m_rotation = 0;
                m_hasSoftShadow = false;
                p->save();
                p->translate(xOffset, yOffset);
                DrawObj(p, QRectF());
                p->colorizeAlpha(tmp);
                if (m_softShadowBlurRadius > 0)
                        p->blur(m_softShadowBlurRadius * sc);
                p->restore();
                if (m_softShadowErasedByObject)
                {
                        p->save();
                        FPointArray sh = PoLine.copy();
                        p->beginLayer(1.0, 18, &sh);
                        p->translate(xOffset - m_softShadowXOffset, yOffset - m_softShadowYOffset);
                        DrawObj(p, QRectF());
                        p->endLayer();
                        p->restore();
                }
                m_fillTransparency = fillTrans_Old;
                m_lineTransparency = lineTrans_Old;
                m_hasSoftShadow = hasSoftShadow_Old;
                m_rotation = rotation_Old;
        }
        else
        {
                FPointArray sh = PoLine.copy();
                sh.translate(m_softShadowXOffset, m_softShadowYOffset);
                p->setupPolygon(&sh);
                p->setBrush(tmp);
                p->setFillMode(ScPainter::Solid);
                p->fillPath();
                if (hasStroke())
                {
                        p->setStrokeMode(ScPainter::Solid);
                        p->setPen(tmp, lwCorr, PLineArt, PLineEnd, PLineJoin);
                        p->strokePath();
                }
                if (m_softShadowBlurRadius > 0)
                        p->blur(m_softShadowBlurRadius * sc);
                if (m_softShadowErasedByObject)
                {
                        sh = PoLine.copy();
                        p->setupPolygon(&sh);
                        p->setBrush(tmp);
                        p->setFillMode(ScPainter::Solid);
                        p->setBlendModeFill(19);
                        p->fillPath();
                        if (hasStroke())
                        {
                                p->setBlendModeStroke(19);
                                p->setStrokeMode(ScPainter::Solid);
                                p->setPen(tmp, lwCorr, PLineArt, PLineEnd, PLineJoin);
                                p->strokePath();
                        }
                }
        }
        p->endLayer();
        p->restore();
}

QImage PageItem::DrawObj_toImage(double maxSize, int options)
{
        bool isEmbedded_Old = isEmbedded;
        double rotation_Old = m_rotation;
        double minx =  std::numeric_limits<double>::max();
        double miny =  std::numeric_limits<double>::max();
        double maxx = -std::numeric_limits<double>::max();
        double maxy = -std::numeric_limits<double>::max();
        double x1, x2, y1, y2;
        if (options & NoRotation)
                m_rotation = 0.0;
        getVisualBoundingRect(&x1, &y1, &x2, &y2);
        m_rotation = rotation_Old;
        double maxAdd = 0;
        if (hasSoftShadow() && !(options & NoSoftShadow))
                maxAdd = qMax(fabs(softShadowXOffset()), fabs(softShadowYOffset())) + softShadowBlurRadius();
        minx = qMin(minx, x1) - maxAdd;
        miny = qMin(miny, y1) - maxAdd;
        maxx = qMax(maxx, x2) + maxAdd;
        maxy = qMax(maxy, y2) + maxAdd;
        double igXpos = xPos() - minx;
        double igYpos = yPos() - miny;
        double igWidth = maxx - minx;
        double igHeight = maxy - miny;
        double sc = maxSize / qMax(igWidth, igHeight);
        bool savedFlag = m_Doc->guidesPrefs().framesShown;
        m_Doc->guidesPrefs().framesShown = false;
        QImage retImg = QImage(qMax(qRound(igWidth * sc), 1), qMax(qRound(igHeight * sc), 1), QImage::Format_ARGB32_Premultiplied);
        retImg.fill( qRgba(0, 0, 0, 0) );
        ScPainter *painter = new ScPainter(&retImg, retImg.width(), retImg.height(), 1, 0);
        painter->setZoomFactor(sc);
        painter->save();
        painter->translate(igXpos, igYpos);
        if (options & NoRotation)
                painter->rotate(-m_rotation);
        if (invalid)
                layout();
        isEmbedded = true;
        DrawObj(painter, QRectF());
        painter->restore();
        painter->end();
        delete painter;
        m_Doc->guidesPrefs().framesShown = savedFlag;
        isEmbedded = isEmbedded_Old;
        if ((isEmbedded_Old != isEmbedded) && (isTextFrame() || isPathText()))
        {
                invalid = true;
                layout();
        }
        return retImg;
}

QImage PageItem::DrawObj_toImage(QList<PageItem*> &emG, double scaling)
{
        bool isEmbedded_Old = isEmbedded;
        bool savedFlag = m_Doc->guidesPrefs().framesShown;
        m_Doc->guidesPrefs().framesShown = false;
        QImage retImg = QImage(qRound(gWidth * scaling), qRound(gHeight * scaling), QImage::Format_ARGB32_Premultiplied);
        retImg.fill( qRgba(0, 0, 0, 0) );
        ScPainter *painter = new ScPainter(&retImg, retImg.width(), retImg.height(), 1, 0);
        painter->setZoomFactor(scaling);
        for (int em = 0; em < emG.count(); ++em)
        {
                PageItem* embedded = emG.at(em);
                painter->save();
                painter->translate(embedded->gXpos, embedded->gYpos);
                embedded->isEmbedded = true;
                embedded->invalid = true;
                embedded->DrawObj(painter, QRectF());
                embedded->isEmbedded = false;
                painter->restore();
        }
        painter->end();
        delete painter;
        m_Doc->guidesPrefs().framesShown = savedFlag;
        isEmbedded = isEmbedded_Old;
        return retImg;
}

void PageItem::SetQColor(QColor *tmp, const QString& colorName, double shad)
{
        if (colorName == CommonStrings::None)
                return;

        const ScColor& col = m_Doc->PageColors[colorName];
        *tmp = ScColorEngine::getShadeColorProof(col, m_Doc, shad);
        if (m_Doc->viewAsPreview)
        {
                VisionDefectColor defect;
                *tmp = defect.convertDefect(*tmp, m_Doc->previewVisual);
        }
}

void PageItem::DrawPolyL(QPainter *p, const QPolygon& pts)
{
        if (Segments.count() == 0)
        {
                p->drawPolygon(pts);
                return;
        }

        QList<uint>::Iterator it2end = Segments.end();
        uint firstVal = 0;
        for (QList<uint>::Iterator it2 = Segments.begin(); it2 != it2end; ++it2)
        {
                p->drawPolygon(pts.constData() + firstVal, (*it2) - firstVal);
                firstVal = (*it2);
        }
        p->drawPolygon(pts.constData() + firstVal, pts.size() - firstVal);
}

void PageItem::setItemName(const QString& newName)
{
        if (m_itemName == newName || newName.isEmpty())
                return;
        QString oldName = m_itemName;
        m_itemName = generateUniqueCopyName(newName);
        AutoName=false;
        if (UndoManager::undoEnabled())
        {
                SimpleState *ss = new SimpleState(Um::Rename, QString(Um::FromTo).arg(oldName, newName));
                ss->set("OLD_NAME", oldName);
                ss->set("NEW_NAME", newName);
                undoManager->action(this, ss);
        }
        setUName(m_itemName); // set the name for the UndoObject too
}

void PageItem::setGradient(const QString &newGradient)
{
        if (m_gradientName == newGradient)
                return;
        m_gradientName = newGradient;
        if (m_Doc->docGradients.contains(m_gradientName))
                fill_gradient = m_Doc->docGradients[m_gradientName];
}

void PageItem::setMaskGradient(const VGradient& grad)
{
        if (mask_gradient==grad)
                return;
        if (UndoManager::undoEnabled())
        {
                ScItemState<QPair<VGradient, VGradient> >* is = new ScItemState<QPair<VGradient,VGradient> >(Um::GradVal);
                is->set("MASK_GRAD");
                is->setItem(qMakePair(mask_gradient, grad));
                undoManager->action(this,is);
        }
        mask_gradient=grad;
}

void PageItem::setFillGradient(const VGradient& grad)
{
        if (fill_gradient==grad)
                return;
        if (UndoManager::undoEnabled())
        {
                ScItemState<QPair<VGradient,VGradient> > *is = new ScItemState<QPair<VGradient,VGradient> >(Um::GradVal);
                is->set("FILL_GRAD");
                is->setItem(qMakePair(fill_gradient, grad));
                undoManager->action(this,is);
        }
        fill_gradient=grad;
}

void PageItem::setStrokeGradient(const VGradient& grad)
{
        if (stroke_gradient==grad)
                return;
        if (UndoManager::undoEnabled())
        {
                ScItemState<QPair<VGradient,VGradient> > *is = new ScItemState<QPair<VGradient,VGradient> >(Um::GradVal);
                is->set("STROKE_GRAD");
                is->setItem(qMakePair(stroke_gradient, grad));
                undoManager->action(this,is);
        }
        stroke_gradient=grad;
}

void PageItem::setPattern(const QString &newPattern)
{
        if (m_patternName != newPattern)
                m_patternName = newPattern;
}

void PageItem::set4ColorGeometry(FPoint c1, FPoint c2, FPoint c3, FPoint c4)
{
        GrControl1 = c1;
        GrControl2 = c2;
        GrControl3 = c3;
        GrControl4 = c4;
}

void PageItem::setDiamondGeometry(const FPoint& c1, const FPoint& c2, const FPoint& c3, const FPoint& c4, const FPoint& c5)
{
        GrControl1 = c1;
        GrControl2 = c2;
        GrControl3 = c3;
        GrControl4 = c4;
        GrControl5 = c5;
}

void PageItem::set4ColorTransparency(double t1, double t2, double t3, double t4)
{
        UndoTransaction trans;
        if (UndoManager::undoEnabled())
                trans = undoManager->beginTransaction(Um::Selection, Um::IFill, Um::GradVal,QString(), Um::IFill);
        setGradientTransp1(t1);
        setGradientTransp2(t2);
        setGradientTransp3(t3);
        setGradientTransp4(t4);
        if (trans)
                trans.commit();
}

void PageItem::set4ColorShade(int t1, int t2, int t3, int t4)
{
        UndoTransaction trans;
        if (UndoManager::undoEnabled())
                trans = undoManager->beginTransaction(Um::Selection, Um::IFill, Um::GradVal, QString(), Um::IFill);
        setGradientShade1(t1);
        setGradientShade2(t2);
        setGradientShade3(t3);
        setGradientShade4(t4);
        if (trans)
                trans.commit();
}

void PageItem::set4ColorColors(const QString& col1, const QString& col2, const QString& col3, const QString& col4)
{
        QColor tmp;
        UndoTransaction trans;
        if (UndoManager::undoEnabled())
                trans = undoManager->beginTransaction(Um::Selection,Um::IFill, Um::GradVal, QString(), Um::IFill);
        setGradientCol1(col1);
        if (GrColorP1 != CommonStrings::None)
        {
                if (!m_Doc->PageColors.contains(GrColorP1))
                {
                        switch (itemType())
                        {
                                case ImageFrame:
                                case LatexFrame:
                                case OSGFrame:
                                        setGradientCol1(m_Doc->itemToolPrefs().imageFillColor);
                                        break;
                                case TextFrame:
                                case PathText:
                                        setGradientCol1(m_Doc->itemToolPrefs().textFillColor);
                                        break;
                                case Line:
                                case PolyLine:
                                case Polygon:
                                case RegularPolygon:
                                case Arc:
                                case Spiral:
                                        setGradientCol1(m_Doc->itemToolPrefs().shapeFillColor);
                                        break;
                                default:
                                        break;
                        }
                }
                const ScColor& col = m_Doc->PageColors[GrColorP1];
                tmp = ScColorEngine::getShadeColorProof(col, m_Doc, GrCol1Shade);
                tmp.setAlphaF(GrCol1transp);
                setGradientColor1(tmp);
        }
        else
                setGradientColor1(QColor(0, 0, 0, 0));
        if (m_Doc->viewAsPreview)
        {
                VisionDefectColor defect;
                setGradientColor1(defect.convertDefect(m_grQColorP1, m_Doc->previewVisual));
        }
        setGradientCol2(col2);
        if (GrColorP2 != CommonStrings::None)
        {
                if (!m_Doc->PageColors.contains(GrColorP2))
                {
                        switch (itemType())
                        {
                                case ImageFrame:
                                case LatexFrame:
                                case OSGFrame:
                                        setGradientCol2(m_Doc->itemToolPrefs().imageFillColor);
                                        break;
                                case TextFrame:
                                case PathText:
                                        setGradientCol2(m_Doc->itemToolPrefs().textFillColor);
                                        break;
                                case Line:
                                case PolyLine:
                                case Polygon:
                                case RegularPolygon:
                                case Arc:
                                case Spiral:
                                        setGradientCol2(m_Doc->itemToolPrefs().shapeFillColor);
                                        break;
                                default:
                                        break;
                        }
                }
                const ScColor& col = m_Doc->PageColors[GrColorP2];
                tmp = ScColorEngine::getShadeColorProof(col, m_Doc, GrCol2Shade);
                tmp.setAlphaF(GrCol2transp);
                setGradientColor2(tmp);
        }
        else
                setGradientColor2(QColor(0, 0, 0, 0));
        if (m_Doc->viewAsPreview)
        {
                VisionDefectColor defect;
                setGradientColor2(defect.convertDefect(m_grQColorP2, m_Doc->previewVisual));
        }
        setGradientCol3(col3);
        if (GrColorP3 != CommonStrings::None)
        {
                if (!m_Doc->PageColors.contains(GrColorP3))
                {
                        switch (itemType())
                        {
                                case ImageFrame:
                                case LatexFrame:
                                case OSGFrame:
                                        setGradientCol3(m_Doc->itemToolPrefs().imageFillColor);
                                        break;
                                case TextFrame:
                                case PathText:
                                        setGradientCol3(m_Doc->itemToolPrefs().textFillColor);
                                        break;
                                case Line:
                                case PolyLine:
                                case Polygon:
                                case RegularPolygon:
                                case Arc:
                                case Spiral:
                                        setGradientCol3(m_Doc->itemToolPrefs().shapeFillColor);
                                        break;
                                default:
                                        break;
                        }
                }
                const ScColor& col = m_Doc->PageColors[GrColorP3];
                tmp = ScColorEngine::getShadeColorProof(col, m_Doc, GrCol3Shade);
                tmp.setAlphaF(GrCol3transp);
                setGradientColor3(tmp);
        }
        else
                setGradientColor3(QColor(0, 0, 0, 0));
        if (m_Doc->viewAsPreview)
        {
                VisionDefectColor defect;
                setGradientColor3(defect.convertDefect(m_grQColorP3, m_Doc->previewVisual));
        }
        setGradientCol4(col4);
        if (GrColorP4 != CommonStrings::None)
        {
                if (!m_Doc->PageColors.contains(GrColorP4))
                {
                        switch (itemType())
                        {
                                case ImageFrame:
                                case LatexFrame:
                                case OSGFrame:
                                        setGradientCol4(m_Doc->itemToolPrefs().imageFillColor);
                                        break;
                                case TextFrame:
                                case PathText:
                                        setGradientCol4(m_Doc->itemToolPrefs().textFillColor);
                                        break;
                                case Line:
                                case PolyLine:
                                case Polygon:
                                case RegularPolygon:
                                case Arc:
                                case Spiral:
                                        setGradientCol4(m_Doc->itemToolPrefs().shapeFillColor);
                                        break;
                                default:
                                        break;
                        }
                }
                const ScColor& col = m_Doc->PageColors[GrColorP4];
                tmp = ScColorEngine::getShadeColorProof(col, m_Doc, GrCol4Shade);
                tmp.setAlphaF(GrCol4transp);
                setGradientColor4(tmp);
        }
        else
                setGradientColor4(QColor(0, 0, 0, 0));
        if (m_Doc->viewAsPreview)
        {
                VisionDefectColor defect;
                setGradientColor4(defect.convertDefect(m_grQColorP4, m_Doc->previewVisual));
        }
        if (trans)
                trans.commit();
}

void PageItem::get4ColorGeometry(FPoint& c1, FPoint& c2, FPoint& c3, FPoint& c4)
{
        c1 = GrControl1;
        c2 = GrControl2;
        c3 = GrControl3;
        c4 = GrControl4;
}

void PageItem::get4ColorTransparency(double &t1, double &t2, double &t3, double &t4)
{
        t1 = GrCol1transp;
        t2 = GrCol2transp;
        t3 = GrCol3transp;
        t4 = GrCol4transp;
}

void PageItem::get4ColorColors(QString &col1, QString &col2, QString &col3, QString &col4)
{
        col1 = GrColorP1;
        col2 = GrColorP2;
        col3 = GrColorP3;
        col4 = GrColorP4;
}

void PageItem::setMeshPointColor(int x, int y, const QString& color, int shade, double transparency, bool forPatch)
{
        QString MColor(color);
        QColor MQColor;
        if (MColor != CommonStrings::None)
        {
                if (!m_Doc->PageColors.contains(MColor))
                {
                        switch (itemType())
                        {
                                case ImageFrame:
                                case LatexFrame:
                                case OSGFrame:
                                        MColor = m_Doc->itemToolPrefs().imageFillColor;
                                        break;
                                case TextFrame:
                                case PathText:
                                        MColor = m_Doc->itemToolPrefs().textFillColor;
                                        break;
                                case Line:
                                case PolyLine:
                                case Polygon:
                                case RegularPolygon:
                                case Arc:
                                case Spiral:
                                        MColor = m_Doc->itemToolPrefs().shapeFillColor;
                                        break;
                                default:
                                        break;
                        }
                }
                const ScColor& col = m_Doc->PageColors[MColor];
                MQColor = ScColorEngine::getShadeColorProof(col, m_Doc, shade);
                MQColor.setAlphaF(transparency);
        }
        else
                MQColor = QColor(0, 0, 0, 0);
        if (m_Doc->viewAsPreview)
        {
                VisionDefectColor defect;
                MQColor = defect.convertDefect(MQColor, m_Doc->previewVisual);
        }
        MeshPoint *mp = nullptr;
        if (forPatch)
        {
                meshGradientPatch *patch = &meshGradientPatches[x];
                switch (y)
                {
                        case 1:
                                mp = &(patch->TL);
                                break;
                        case 2:
                                mp = &(patch->TR);
                                break;
                        case 3:
                                mp = &(patch->BR);
                                break;
                        case 4:
                                mp = &(patch->BL);
                                break;
                }

                UndoTransaction trans;
                if (UndoManager::undoEnabled())
                {
                        trans = undoManager->beginTransaction(Um::Selection, Um::IFill, Um::GradVal, QString(), Um::IFill);
                        ScItemState<QPair<QColor, QColor> >* ss = new ScItemState<QPair<QColor,QColor> >(Um::GradVal);
                        ss->set("GRAD_MESH_COLOR");
                        ss->set("X",x);
                        ss->set("Y",y);
                        ss->set("PATCH",true);
                        ss->set("OLD_COLOR_NAME",mp->colorName);
                        ss->set("NEW_COLOR_NAME",MColor);
                        ss->setItem(qMakePair(mp->color,MQColor));
                        ss->set("OLD_SHADE",mp->shade);
                        ss->set("NEW_SHADE",shade);
                        ss->set("OLD_TRANSP",mp->transparency);
                        ss->set("NEW_TRANSP",transparency);
                        undoManager->action(this, ss);
                }
                mp->colorName = MColor;
                mp->color = MQColor;
                mp->shade = shade;
                mp->transparency = transparency;
                FPoint xx = mp->gridPoint;
                for (int col = 0; col < meshGradientPatches.count(); col++)
                {
                        if (col != x)
                        {
                                if (meshGradientPatches[col].TL.gridPoint == xx)
                                {
                                        mp = &(meshGradientPatches[col].TL);
                                        if (UndoManager::undoEnabled())
                                        {
                                                ScItemState<QPair<QColor, QColor> >* ss = new ScItemState<QPair<QColor,QColor> >(Um::GradVal);
                                                ss->set("GRAD_MESH_COLOR");
                                                ss->set("X",col);
                                                ss->set("Y",1);
                                                ss->set("PATCH",true);
                                                ss->set("OLD_COLOR_NAME",mp->colorName);
                                                ss->set("NEW_COLOR_NAME",MColor);
                                                ss->setItem(qMakePair(mp->color,MQColor));
                                                ss->set("OLD_SHADE",mp->shade);
                                                ss->set("NEW_SHADE",shade);
                                                ss->set("OLD_TRANSP",mp->transparency);
                                                ss->set("NEW_TRANSP",transparency);
                                                undoManager->action(this, ss);
                                        }
                                        mp->colorName = MColor;
                                        mp->color = MQColor;
                                        mp->shade = shade;
                                        mp->transparency = transparency;
                                }
                                if (meshGradientPatches[col].TR.gridPoint == xx)
                                {
                                        mp = &(meshGradientPatches[col].TR);
                                        if (UndoManager::undoEnabled())
                                        {
                                                ScItemState<QPair<QColor, QColor> >* ss = new ScItemState<QPair<QColor,QColor> >(Um::GradVal);
                                                ss->set("GRAD_MESH_COLOR");
                                                ss->set("X",col);
                                                ss->set("Y",2);
                                                ss->set("PATCH",true);
                                                ss->set("OLD_COLOR_NAME",mp->colorName);
                                                ss->set("NEW_COLOR_NAME",MColor);
                                                ss->setItem(qMakePair(mp->color,MQColor));
                                                ss->set("OLD_SHADE",mp->shade);
                                                ss->set("NEW_SHADE",shade);
                                                ss->set("OLD_TRANSP",mp->transparency);
                                                ss->set("NEW_TRANSP",transparency);
                                                undoManager->action(this, ss);
                                        }
                                        mp->colorName = MColor;
                                        mp->color = MQColor;
                                        mp->shade = shade;
                                        mp->transparency = transparency;
                                }
                                if (meshGradientPatches[col].BR.gridPoint == xx)
                                {
                                        mp = &(meshGradientPatches[col].BR);
                                        if (UndoManager::undoEnabled())
                                        {
                                                ScItemState<QPair<QColor, QColor> >* ss = new ScItemState<QPair<QColor,QColor> >(Um::GradVal);
                                                ss->set("GRAD_MESH_COLOR");
                                                ss->set("X",col);
                                                ss->set("Y",3);
                                                ss->set("PATCH",true);
                                                ss->set("OLD_COLOR_NAME",mp->colorName);
                                                ss->set("NEW_COLOR_NAME",MColor);
                                                ss->setItem(qMakePair(mp->color,MQColor));
                                                ss->set("OLD_SHADE",mp->shade);
                                                ss->set("NEW_SHADE",shade);
                                                ss->set("OLD_TRANSP",mp->transparency);
                                                ss->set("NEW_TRANSP",transparency);
                                                undoManager->action(this, ss);
                                        }
                                        mp->colorName = MColor;
                                        mp->color = MQColor;
                                        mp->shade = shade;
                                        mp->transparency = transparency;
                                }
                                if (meshGradientPatches[col].BL.gridPoint == xx)
                                {
                                        mp = &(meshGradientPatches[col].BL);
                                        if (UndoManager::undoEnabled())
                                        {
                                                ScItemState<QPair<QColor, QColor> >* ss = new ScItemState<QPair<QColor,QColor> >(Um::GradVal);
                                                ss->set("GRAD_MESH_COLOR");
                                                ss->set("X",col);
                                                ss->set("Y",4);
                                                ss->set("PATCH",true);
                                                ss->set("OLD_COLOR_NAME",mp->colorName);
                                                ss->set("NEW_COLOR_NAME",MColor);
                                                ss->setItem(qMakePair(mp->color,MQColor));
                                                ss->set("OLD_SHADE",mp->shade);
                                                ss->set("NEW_SHADE",shade);
                                                ss->set("OLD_TRANSP",mp->transparency);
                                                ss->set("NEW_TRANSP",transparency);
                                                undoManager->action(this, ss);
                                        }
                                        mp->colorName = MColor;
                                        mp->color = MQColor;
                                        mp->shade = shade;
                                        mp->transparency = transparency;
                                }
                        }
                }
                if (trans)
                        trans.commit();
        }
        else
        {
                if ((x > -1) && (y > -1))
                {
                        mp = &(meshGradientArray[x][y]);
                        if (UndoManager::undoEnabled())
                        {
                                ScItemState<QPair<QColor, QColor> >* ss = new ScItemState<QPair<QColor,QColor> >(Um::GradVal);
                                ss->set("GRAD_MESH_COLOR");
                                ss->set("X",x);
                                ss->set("Y",y);
                                ss->set("PATCH",false);
                                ss->set("OLD_COLOR_NAME",mp->colorName);
                                ss->set("NEW_COLOR_NAME",MColor);
                                ss->setItem(qMakePair(mp->color,MQColor));
                                ss->set("OLD_SHADE",mp->shade);
                                ss->set("NEW_SHADE",shade);
                                ss->set("OLD_TRANSP",mp->transparency);
                                ss->set("NEW_TRANSP",transparency);
                                undoManager->action(this, ss);
                        }
                        mp->colorName = MColor;
                        mp->color = MQColor;
                        mp->shade = shade;
                        mp->transparency = transparency;
                }
        }
}

void PageItem::createGradientMesh(int rows, int cols)
{
        QString MColor(m_fillColor);
        QColor MQColor;
        if (m_fillColor != CommonStrings::None)
        {
                if (!m_Doc->PageColors.contains(m_fillColor))
                {
                        switch (itemType())
                        {
                                case ImageFrame:
                                case LatexFrame:
                                case OSGFrame:
                                        MColor = m_Doc->itemToolPrefs().imageFillColor;
                                        break;
                                case TextFrame:
                                case PathText:
                                        MColor = m_Doc->itemToolPrefs().textFillColor;
                                        break;
                                case Line:
                                case PolyLine:
                                case Polygon:
                                case RegularPolygon:
                                case Arc:
                                case Spiral:
                                        MColor = m_Doc->itemToolPrefs().shapeFillColor;
                                        break;
                                default:
                                        break;
                        }
                }
                const ScColor& col = m_Doc->PageColors[MColor];
                MQColor = ScColorEngine::getShadeColorProof(col, m_Doc, 100);
                MQColor.setAlphaF(1.0);
        }
        else
                MQColor = QColor(0, 0, 0, 0);
        if (m_Doc->viewAsPreview)
        {
                VisionDefectColor defect;
                MQColor = defect.convertDefect(MQColor, m_Doc->previewVisual);
        }
        if (UndoManager::undoEnabled())
        {
                ScItemState<QList<QList<MeshPoint> > >* is = new ScItemState<QList<QList<MeshPoint> > >(Um::MeshGradient);
                is->set("CREATE_MESH_GRAD");
                is->set("ROW",rows);
                is->set("COL",cols);
                is->setItem(meshGradientArray);
                undoManager->action(this,is);
        }
        meshGradientArray.clear();
        if (rows == 0 || cols == 0)
                qFatal("PageItem::createGradientMesh: rows or cols is 0");
        double xoffs = m_width / static_cast<double>(cols);
        double yoffs = m_height / static_cast<double>(rows);
        for (int x = 0; x < rows + 1; x++)
        {
                QList<MeshPoint> mgList;
                mgList.reserve(cols + 1);
                for (int y = 0; y < cols + 1; y++)
                {
                        MeshPoint mgP;
                        mgP.resetTo(FPoint(y * xoffs, x * yoffs));
                        mgP.transparency = 1.0;
                        mgP.shade = 100;
                        mgP.colorName = MColor;
                        mgP.color = MQColor;
                        mgList.append(mgP);
                }
                meshGradientArray.append(mgList);
        }
}

void PageItem::resetGradientMesh()
{
        int rows = meshGradientArray.count();
        int cols = meshGradientArray[0].count();
        if (UndoManager::undoEnabled())
        {
                ScItemState<QList<QList<MeshPoint> > > *is = new ScItemState<QList<QList<MeshPoint> > >(Um::ResetControlPoints);
                is->set("RESET_MESH_GRAD");
                is->setItem(meshGradientArray);
                undoManager->action(this,is);
        }
        double xoffs = m_width / static_cast<double>(cols-1);
        double yoffs = m_height / static_cast<double>(rows-1);
        for (int x = 0; x < rows; x++)
                for (int y = 0; y < cols; y++)
                        meshGradientArray[x][y].resetTo(FPoint(y * xoffs, x * yoffs));
}

void PageItem::meshToShape()
{
        FPointArray Coords;
        Coords.resize(0);
        Coords.svgInit();
        int rows = meshGradientArray.count() - 1;
        int cols = meshGradientArray[0].count() - 1;
        QList<MeshPoint> mpList;
        mpList = meshGradientArray[0];
        Coords.svgMoveTo(mpList[0].gridPoint.x(), mpList[0].gridPoint.y());
        for (int m = 0; m < mpList.count()-1; m++)
        {
                Coords.svgCurveToCubic(mpList[m].controlRight.x(), mpList[m].controlRight.y(),
                                                                mpList[m+1].controlLeft.x(), mpList[m+1].controlLeft.y(),
                                                                mpList[m+1].gridPoint.x(), mpList[m+1].gridPoint.y());
        }
        for (int m = 0; m < rows; m++)
        {
                Coords.svgCurveToCubic(meshGradientArray[m][cols].controlBottom.x(), meshGradientArray[m][cols].controlBottom.y(),
                                                                meshGradientArray[m+1][cols].controlTop.x(), meshGradientArray[m+1][cols].controlTop.y(),
                                                                meshGradientArray[m+1][cols].gridPoint.x(), meshGradientArray[m+1][cols].gridPoint.y());
        }
        mpList = meshGradientArray[rows];
        for (int m = cols; m > 0; m--)
        {
                Coords.svgCurveToCubic(mpList[m].controlLeft.x(), mpList[m].controlLeft.y(),
                                                                mpList[m-1].controlRight.x(), mpList[m-1].controlRight.y(),
                                                                mpList[m-1].gridPoint.x(), mpList[m-1].gridPoint.y());
        }
        for (int m = rows; m > 0; m--)
        {
                Coords.svgCurveToCubic(meshGradientArray[m][0].controlTop.x(), meshGradientArray[m][0].controlTop.y(),
                                                                meshGradientArray[m-1][0].controlBottom.x(), meshGradientArray[m-1][0].controlBottom.y(),
                                                                meshGradientArray[m-1][0].gridPoint.x(), meshGradientArray[m-1][0].gridPoint.y());
        }
       
        UndoTransaction trans;
        if (UndoManager::undoEnabled())
        {
                trans = undoManager->beginTransaction(Um::Selection, Um::IFill, Um::ChangeMeshGradient, QString(), Um::IFill);
                ScItemState<QPair<QList<QList<MeshPoint> >,FPointArray> > *ism = new ScItemState<QPair<QList<QList<MeshPoint> >,FPointArray> >(Um::ChangeMeshGradient, QString(), Um::IFill);
                ism->set("MOVE_MESH_GRAD");
                ism->setItem(qMakePair(meshGradientArray,PoLine));
                ism->set("OLDB",OldB2);
                ism->set("OLDH",OldH2);
                ism->set("FRAME_TYPE",FrameType);
                undoManager->action(this, ism);
        }
        QList<QList<MeshPoint> > meshGradientArrayOld = meshGradientArray;
        PoLine = Coords.copy();
        double oldX = m_xPos;
        double oldY = m_yPos;
        ClipEdited = true;
        FrameType = 3;
        FPoint wh = getMaxClipF(&PoLine);
        setWidthHeight(wh.x(),wh.y());
        m_Doc->adjustItemSize(this);
        OldB2 = width();
        OldH2 = height();
        updateClip();
        meshGradientArray = meshGradientArrayOld;
        double dx = oldX - m_xPos;
        double dy = oldY - m_yPos;
        for (int x = 0; x < rows+1; x++)
                for (int y = 0; y < cols+1; y++)
                        meshGradientArray[x][y].moveRel(dx, dy);
        if (UndoManager::undoEnabled())
        {
                ScItemState<FPointArray> *is = new ScItemState<FPointArray>(Um::ResetContourLine, QString(), Um::IBorder);
                is->set("RESET_CONTOUR");
                is->setItem(ContourLine);
                undoManager->action(this, is);
        }
        ContourLine = PoLine.copy();
        if (trans)
                trans.commit();
}

void PageItem::createConicalMesh()
{
        VGradient gradient;
        gradient.clearStops();
        if (fill_gradient.stops() < 2)
        {
                fill_gradient.clearStops();
                const ScColor& col = m_Doc->PageColors["Black"];
                QColor qcol = ScColorEngine::getRGBColor(col, m_Doc);
                fill_gradient.addStop(qcol, 0.0, 0.5, 1.0, "Black", 100);
                const ScColor& col2 = m_Doc->PageColors["White"];
                qcol = ScColorEngine::getRGBColor(col2, m_Doc);
                fill_gradient.addStop(qcol, 1.0, 0.5, 1.0, "White", 100);
        }
        QList<VColorStop*> cstops = fill_gradient.colorStops();
        double lastStop = -1.0;
        double actualStop = 0.0;
        bool isFirst = true;
        for (int cst = 0; cst < fill_gradient.stops(); ++cst)
        {
                actualStop = cstops.at(cst)->rampPoint;
                if ((actualStop == lastStop) && (!isFirst))
                        continue;
                if (isFirst)
                {
                        if (actualStop != 0.0)
                        {
                                gradient.addStop(cstops.at(cst)->color, 0, 0, cstops.at(cst)->opacity, cstops.at(cst)->name, cstops.at(cst)->shade);
                                if (actualStop <= 0.25)
                                        gradient.addStop(cstops.at(cst)->color, cstops.at(cst)->rampPoint, cstops.at(cst)->midPoint, cstops.at(cst)->opacity, cstops.at(cst)->name, cstops.at(cst)->shade);
                                else
                                {
                                        double actDist = 0.25;
                                        do
                                        {
                                                gradient.addStop(cstops.at(cst)->color, actDist, actDist, cstops.at(cst)->opacity, cstops.at(cst)->name, cstops.at(cst)->shade);
                                                actDist += 0.25;
                                        }
                                        while (actualStop > actDist);
                                        gradient.addStop(cstops.at(cst)->color, cstops.at(cst)->rampPoint, cstops.at(cst)->midPoint, cstops.at(cst)->opacity, cstops.at(cst)->name, cstops.at(cst)->shade);
                                }
                        }
                        else
                                gradient.addStop(cstops.at(cst)->color, cstops.at(cst)->rampPoint, cstops.at(cst)->midPoint, cstops.at(cst)->opacity, cstops.at(cst)->name, cstops.at(cst)->shade);
                        isFirst = false;
                        lastStop = actualStop;
                        continue;
                }
                isFirst = false;
                if (actualStop - lastStop <= 0.25)
                        gradient.addStop(cstops.at(cst)->color, cstops.at(cst)->rampPoint, cstops.at(cst)->midPoint, cstops.at(cst)->opacity, cstops.at(cst)->name, cstops.at(cst)->shade);
                else
                {
                        double actDist = lastStop + 0.25;
                        do
                        {
                                gradient.addStop(computeInBetweenStop(cstops.at(cst-1), cstops.at(cst), actDist));
                                actDist += 0.25;
                        }
                        while (actualStop > actDist);
                        gradient.addStop(cstops.at(cst)->color, cstops.at(cst)->rampPoint, cstops.at(cst)->midPoint, cstops.at(cst)->opacity, cstops.at(cst)->name, cstops.at(cst)->shade);
                }
                if ((cst == fill_gradient.stops()-1) && (actualStop < 1.0))
                {
                        double distToGo = 1.0 - actualStop;
                        if (distToGo <= 0.25)
                                gradient.addStop(cstops.at(cst)->color, 1.0, 1.0, cstops.at(cst)->opacity, cstops.at(cst)->name, cstops.at(cst)->shade);
                        else
                        {
                                do
                                {
                                        double actDist = actualStop + 0.25;
                                        gradient.addStop(cstops.at(cst)->color, actDist, actDist, cstops.at(cst)->opacity, cstops.at(cst)->name, cstops.at(cst)->shade);
                                        distToGo -= 0.25;
                                        actDist += 0.25;
                                }
                                while (distToGo >= 0.25);
                                gradient.addStop(cstops.at(cst)->color, 1.0, 1.0, cstops.at(cst)->opacity, cstops.at(cst)->name, cstops.at(cst)->shade);
                        }
                        break;
                }
                lastStop = actualStop;
        }
        meshGradientArray.clear();
        QList<MeshPoint> mgList1;
        QList<MeshPoint> mgList2;
        MeshPoint mgP1, mgP2, mgP3, mgP4;
        QPainterPath path;
        FPointArray arcPath;
        QLineF angLin = QLineF(QPointF(GrStartX, GrStartY), QPointF(GrEndX, GrEndY));
        double startAngle = angLin.angle();
        double radius = angLin.length();
        double radius2 = radius * 2.0;
        QList<VColorStop*> rstops = gradient.colorStops();
        if (rstops.count() < 2)
        {
                const VColorStop* firstStop = rstops.at(0);
                if (firstStop->rampPoint > 0)
                {
                        VColorStop* newStop = new VColorStop(*firstStop);
                        newStop->rampPoint = 0;
                        rstops.prepend(newStop);
                }
                if (firstStop->rampPoint < 1.0)
                {
                        VColorStop* newStop = new VColorStop(*firstStop);
                        newStop->rampPoint = 1.0;
                        rstops.append(newStop);
                }
        }
        double stepAngle = 360 * rstops.at(1)->rampPoint;
        path.arcMoveTo(-radius, -radius, radius2, radius2, 0);
        path.arcTo(-radius, -radius, radius2, radius2, 0, -stepAngle);
        QTransform mm;
        mm.rotate(-startAngle);
        path = mm.map(path);
        QTransform mr;
        mr.scale(1.0, GrScale);
        path = mr.map(path);
        arcPath.fromQPainterPath(path);
        arcPath.translate(GrStartX, GrStartY);
        QPointF foc = QPointF(GrFocalX, GrFocalY);
        QTransform qmatrix;
        qmatrix.translate(GrStartX, GrStartY);
        qmatrix.rotate(-startAngle);
        qmatrix.translate(0, GrStartY * (1.0 - GrScale));
        qmatrix.translate(-GrStartX, -GrStartY);
        qmatrix.scale(1, GrScale);
        foc = qmatrix.map(foc);
        mgP1.resetTo(arcPath.point(0));
        mgP1.controlRight = arcPath.point(1);
        mgP1.transparency = rstops.at(0)->opacity;
        mgP1.shade = rstops.at(0)->shade;
        mgP1.colorName = rstops.at(0)->name;
        mgP1.color = rstops.at(0)->color;
        mgP1.color.setAlphaF(mgP1.transparency);
        mgList1.append(mgP1);

        mgP2.resetTo(arcPath.point(2));
        mgP2.controlLeft = arcPath.point(3);
        mgP2.transparency = rstops.at(1)->opacity;
        mgP2.shade = rstops.at(1)->shade;
        mgP2.colorName = rstops.at(1)->name;
        mgP2.color = rstops.at(1)->color;
        mgP2.color.setAlphaF(mgP2.transparency);

        mgP3.resetTo(FPoint(foc.x(), foc.y()));
        mgP3.transparency = rstops.at(0)->opacity;
        mgP3.shade = rstops.at(0)->shade;
        mgP3.colorName = rstops.at(0)->name;
        mgP3.color = rstops.at(0)->color;
        mgP3.color.setAlphaF(mgP3.transparency);

        mgList2.append(mgP3);
        mgP3.transparency = rstops.at(1)->opacity;
        mgP3.shade = rstops.at(1)->shade;
        mgP3.colorName = rstops.at(1)->name;
        mgP3.color = rstops.at(1)->color;
        mgP3.color.setAlphaF(mgP3.transparency);
        mgList2.append(mgP3);
        startAngle -= stepAngle;
        for (int rst = 2; rst < gradient.stops(); ++rst)
        {
                stepAngle = 360 * (rstops.at(rst)->rampPoint - rstops.at(rst-1)->rampPoint);
                if (stepAngle <= 0)
                        continue;
                path = QPainterPath();
                arcPath.resize(0);
                path.arcMoveTo(-radius, -radius, radius2, radius2, 0);
                path.arcTo(-radius, -radius, radius2, radius2, 0, -stepAngle);
                QTransform mm;
                mm.rotate(-startAngle);
                QTransform mr;
                mr.scale(1.0, GrScale);
                path = mm.map(path);
                path = mr.map(path);
                arcPath.fromQPainterPath(path);
                arcPath.translate(GrStartX, GrStartY);
                mgP2.controlRight = arcPath.point(1);
                mgList1.append(mgP2);

                mgP2.resetTo(arcPath.point(2));
                mgP2.controlLeft = arcPath.point(3);
                mgP2.transparency = rstops.at(rst)->opacity;
                mgP2.shade = rstops.at(rst)->shade;
                mgP2.colorName = rstops.at(rst)->name;
                mgP2.color = rstops.at(rst)->color;
                mgP2.color.setAlphaF(mgP2.transparency);

                mgP3.transparency = rstops.at(rst)->opacity;
                mgP3.shade = rstops.at(rst)->shade;
                mgP3.colorName = rstops.at(rst)->name;
                mgP3.color = rstops.at(rst)->color;
                mgP3.color.setAlphaF(mgP3.transparency);
                mgList2.append(mgP3);
                startAngle -= stepAngle;
        }
        mgList1.append(mgP2);
        meshGradientArray.append(mgList1);
        meshGradientArray.append(mgList2);
}

VColorStop PageItem::computeInBetweenStop(VColorStop* last, VColorStop* actual, double t)
{
        double dist = actual->rampPoint - last->rampPoint;
        double perc = (t - last->rampPoint) / dist;
        double Rn = ((actual->color.redF() - last->color.redF()) * perc) + last->color.redF();
        double Gn = ((actual->color.greenF() - last->color.greenF()) * perc) + last->color.greenF();
        double Bn = ((actual->color.blueF() - last->color.blueF()) * perc) + last->color.blueF();
        QColor color;
        color.setRgbF(Rn, Gn, Bn);
        double opacity = ((actual->opacity - last->opacity) * perc) + last->opacity;
        int shade = qRound(((actual->shade - last->shade) * perc) + last->shade);
        QString name = last->name + actual->name + QString("%1").arg(perc);
        return VColorStop(t, t, color, opacity, name, shade);
}

void PageItem::gradientVector(double& startX, double& startY, double& endX, double& endY, double &focalX, double &focalY, double &scale, double &skew) const
{
        startX = GrStartX;
        startY = GrStartY;
        endX   = GrEndX;
        endY   = GrEndY;
        focalX = GrFocalX;
        focalY = GrFocalY;
        scale  = GrScale;
        skew   = GrSkew;
}

void PageItem::setGradientVector(double startX, double startY, double endX, double endY, double focalX, double focalY, double scale, double skew)
{
        GrStartX = startX;
        GrStartY = startY;
        GrEndX   = endX;
        GrEndY   = endY;
        GrFocalX = focalX;
        GrFocalY = focalY;
        GrScale  = scale;
        GrSkew   = skew;
}

void PageItem::setStrokeGradient(const QString &newGradient)
{
        if (gradientStrokeVal != newGradient)
                gradientStrokeVal = newGradient;
}

void PageItem::strokeGradientVector(double& startX, double& startY, double& endX, double& endY, double &focalX, double &focalY, double &scale, double &skew) const
{
        startX = GrStrokeStartX;
        startY = GrStrokeStartY;
        endX   = GrStrokeEndX;
        endY   = GrStrokeEndY;
        focalX = GrStrokeFocalX;
        focalY = GrStrokeFocalY;
        scale  = GrStrokeScale;
        skew   = GrStrokeSkew;
}

void PageItem::setStrokeGradientVector(double startX, double startY, double endX, double endY, double focalX, double focalY, double scale, double skew)
{
        GrStrokeStartX = startX;
        GrStrokeStartY = startY;
        GrStrokeEndX   = endX;
        GrStrokeEndY   = endY;
        GrStrokeFocalX = focalX;
        GrStrokeFocalY = focalY;
        GrStrokeScale  = scale;
        GrStrokeSkew   = skew;
}

void PageItem::setPatternTransform(double scaleX, double scaleY, double offsetX, double offsetY, double rotation, double skewX, double skewY)
{
        patternScaleX = scaleX;
        patternScaleY = scaleY;
        patternOffsetX = offsetX;
        patternOffsetY = offsetY;
        patternRotation = rotation;
        patternSkewX = skewX;
        patternSkewY = skewY;
}

void PageItem::patternTransform(double &scaleX, double &scaleY, double &offsetX, double &offsetY, double &rotation, double &skewX, double &skewY) const
{
         scaleX = patternScaleX;
         scaleY = patternScaleY;
         offsetX = patternOffsetX;
         offsetY = patternOffsetY;
         rotation = patternRotation;
         skewX = patternSkewX;
         skewY = patternSkewY;
}

void PageItem::setPatternFlip(bool flipX, bool flipY)
{
        patternMirrorX = flipX;
        patternMirrorY = flipY;
}

void PageItem::patternFlip(bool &flipX, bool &flipY)
{
        flipX = patternMirrorX;
        flipY = patternMirrorY;
}

void PageItem::setMaskType(int val)
{
        if (GrMask == val)
                return;
        if (UndoManager::undoEnabled())
        {
                SimpleState *ss = new SimpleState(Um::GradTypeMask, QString(), Um::IFill);
                ss->set("MASKTYPE");
                ss->set("NEW", val);
                ss->set("OLD", GrMask);
                undoManager->action(this, ss);
        }
        GrMask = val;
}

void PageItem::setGradientMask(const QString &newMask)
{
        if (gradientMaskVal != newMask)
                gradientMaskVal = newMask;
}

void PageItem::setPatternMask(const QString &newMask)
{
        if (patternMaskVal != newMask)
                patternMaskVal = newMask;
}

void PageItem::maskVector(double& startX, double& startY, double& endX, double& endY, double &focalX, double &focalY, double &scale, double &skew) const
{
        startX = GrMaskStartX;
        startY = GrMaskStartY;
        endX   = GrMaskEndX;
        endY   = GrMaskEndY;
        focalX = GrMaskFocalX;
        focalY = GrMaskFocalY;
        scale  = GrMaskScale;
        skew   = GrMaskSkew;
}

void PageItem::setMaskVector(double startX, double startY, double endX, double endY, double focalX, double focalY, double scale, double skew)
{
        GrMaskStartX = startX;
        GrMaskStartY = startY;
        GrMaskEndX   = endX;
        GrMaskEndY   = endY;
        GrMaskFocalX = focalX;
        GrMaskFocalY = focalY;
        GrMaskScale  = scale;
        GrMaskSkew   = skew;
}

void PageItem::maskTransform(double &scaleX, double &scaleY, double &offsetX, double &offsetY, double &rotation, double &skewX, double &skewY) const
{
         scaleX = patternMaskScaleX;
         scaleY = patternMaskScaleY;
         offsetX = patternMaskOffsetX;
         offsetY = patternMaskOffsetY;
         rotation = patternMaskRotation;
         skewX = patternMaskSkewX;
         skewY = patternMaskSkewY;
}

void PageItem::setMaskTransform(double scaleX, double scaleY, double offsetX, double offsetY, double rotation, double skewX, double skewY)
{
        patternMaskScaleX = scaleX;
        patternMaskScaleY = scaleY;
        patternMaskOffsetX = offsetX;
        patternMaskOffsetY = offsetY;
        patternMaskRotation = rotation;
        patternMaskSkewX = skewX;
        patternMaskSkewY = skewY;
}

void PageItem::setMaskFlip(bool flipX, bool flipY)
{
        patternMaskMirrorX = flipX;
        patternMaskMirrorY = flipY;
}

void PageItem::maskFlip(bool &flipX, bool &flipY)
{
        flipX = patternMaskMirrorX;
        flipY = patternMaskMirrorY;
}

void PageItem::setFillColor(const QString &newColor)
{
        QString tmp = newColor;
        if (tmp != CommonStrings::None)
        {
                if (!m_Doc->PageColors.contains(newColor))
                {
                        switch (itemType())
                        {
                                case ImageFrame:
                                case LatexFrame:
                                case OSGFrame:
                                        tmp = m_Doc->itemToolPrefs().imageFillColor;
                                        break;
                                case TextFrame:
                                case PathText:
                                        tmp = m_Doc->itemToolPrefs().textFillColor;
                                        break;
                                case Line:
                                case PolyLine:
                                case Polygon:
                                case RegularPolygon:
                                case Arc:
                                case Spiral:
                                        tmp = m_Doc->itemToolPrefs().shapeFillColor;
                                        break;
                                default:
                                        break;
                        }
                }
        }
        if (m_fillColor == tmp)
        {
                setFillQColor();
                return;
        }
        if (UndoManager::undoEnabled())
        {
                SimpleState *ss = new SimpleState(Um::SetFill,
                                                                                  QString(Um::ColorFromTo).arg(m_fillColor, tmp),
                                          Um::IFill);
                ss->set("FILL");
                ss->set("OLD_FILL", m_fillColor);
                ss->set("NEW_FILL", tmp);
                undoManager->action(this, ss);
        }
        m_fillColor = tmp;
        setFillQColor();
}

void PageItem::setFillShade(double newShade)
{
        if (m_fillShade == newShade)
        {
                setFillQColor();
                return;
        }
        if (UndoManager::undoEnabled())
        {
                SimpleState *ss = new SimpleState(Um::SetShade,
                                                                                  QString(Um::FromTo).arg(m_fillShade).arg(newShade),
                                                                                  Um::IShade);
                ss->set("SHADE");
                ss->set("OLD_SHADE", m_fillShade);
                ss->set("NEW_SHADE", newShade);
                undoManager->action(this, ss);
        }
        m_fillShade = newShade;
        setFillQColor();
}

void PageItem::setFillTransparency(double newTransparency)
{
        if (m_fillTransparency == newTransparency)
                return; // nothing to do -> return
        if (UndoManager::undoEnabled())
        {
                SimpleState *ss = new SimpleState(Um::Transparency,
                                                                                  QString(Um::FromTo).arg(m_fillTransparency).arg(newTransparency),
                                                                                  Um::ITransparency);
                ss->set("TRANSPARENCY");
                ss->set("OLD_TP", m_fillTransparency);
                ss->set("NEW_TP", newTransparency);
                undoManager->action(this, ss);
        }
        m_fillTransparency = newTransparency;
}

void PageItem::setFillBlendmode(int newBlendmode)
{
        if (m_fillBlendMode == newBlendmode)
                return; // nothing to do -> return
        if (UndoManager::undoEnabled())
        {
                SimpleState *ss = new SimpleState(Um::BlendMode, nullptr, Um::IGroup);
                ss->set("FILLBLENDMODE", newBlendmode);
                ss->set("FILLBLENDMODE_OLD", m_fillBlendMode);
                undoManager->action(this, ss);
        }
        m_fillBlendMode = newBlendmode;
}

void PageItem::setLineColor(const QString &newColor)
{
        QString tmp = newColor;
        if (tmp != CommonStrings::None)
        {
                if (!m_Doc->PageColors.contains(newColor))
                {
                        switch (itemType())
                        {
                                case TextFrame:
                                case PathText:
                                        tmp = m_Doc->itemToolPrefs().textLineColor;
                                        break;
                                case Line:
                                        tmp = m_Doc->itemToolPrefs().lineColor;
                                        break;
                                case PolyLine:
                                case Polygon:
                                case ImageFrame:
                                case LatexFrame:
                                case OSGFrame:
                                case RegularPolygon:
                                case Arc:
                                case Spiral:
                                        tmp = m_Doc->itemToolPrefs().shapeLineColor;
                                        break;
                                default:
                                        break;
                        }
                }
        }
        if (m_lineColor == tmp)
        {
                setLineQColor();
                return;
        }
        if (UndoManager::undoEnabled())
        {
                SimpleState *ss = new SimpleState(Um::SetLineColor,
                                                                                  QString(Um::ColorFromTo).arg(m_lineColor, tmp),
                                                                                  Um::IFill);
                ss->set("LINE_COLOR");
                ss->set("OLD_COLOR", m_lineColor);
                ss->set("NEW_COLOR", tmp);
                undoManager->action(this, ss);
        }
        m_lineColor = tmp;
        setLineQColor();
}

void PageItem::setLineShade(double newShade)
{
        if (m_lineShade == newShade)
        {
                setLineQColor();
                return;
        }
        if (UndoManager::undoEnabled())
        {
                SimpleState *ss = new SimpleState(Um::SetLineShade,
                                                                                  QString(Um::FromTo).arg(m_lineShade).arg(newShade),
                                                                                  Um::IShade);
                ss->set("LINE_SHADE");
                ss->set("OLD_SHADE", m_lineShade);
                ss->set("NEW_SHADE", newShade);
                undoManager->action(this, ss);
        }
        m_lineShade = newShade;
        setLineQColor();
}

void PageItem::setStrokePattern(const QString &newPattern)
{
        if (patternStrokeVal != newPattern)
                patternStrokeVal = newPattern;
}

void PageItem::setStrokePatternToPath(bool enable)
{
        patternStrokePath = enable;
}

bool PageItem::isStrokePatternToPath()
{
        return patternStrokePath;
}

void PageItem::setStrokePatternTransform(double scaleX, double scaleY, double offsetX, double offsetY, double rotation, double skewX, double skewY, double space)
{
        patternStrokeScaleX = scaleX;
        patternStrokeScaleY = scaleY;
        patternStrokeOffsetX = offsetX;
        patternStrokeOffsetY = offsetY;
        patternStrokeRotation = rotation;
        patternStrokeSkewX = skewX;
        patternStrokeSkewY = skewY;
        patternStrokeSpace = space;
}

void PageItem::setStrokePatternFlip(bool flipX, bool flipY)
{
        patternStrokeMirrorX = flipX;
        patternStrokeMirrorY = flipY;
}

void PageItem::strokePatternFlip(bool &flipX, bool &flipY)
{
        flipX = patternStrokeMirrorX;
        flipY = patternStrokeMirrorY;
}

void PageItem::strokePatternTransform(double &scaleX, double &scaleY, double &offsetX, double &offsetY, double &rotation, double &skewX, double &skewY, double &space) const
{
        scaleX = patternStrokeScaleX;
        scaleY = patternStrokeScaleY;
        offsetX = patternStrokeOffsetX;
        offsetY = patternStrokeOffsetY;
        rotation = patternStrokeRotation;
        skewX = patternStrokeSkewX;
        skewY = patternStrokeSkewY;
        space = patternStrokeSpace;
}

void PageItem::setLineQColor()
{
        if (m_lineColor != CommonStrings::None)
        {
                if (!m_Doc->PageColors.contains(m_lineColor))
                {
                        switch (itemType())
                        {
                                case TextFrame:
                                case PathText:
                                        m_lineColor = m_Doc->itemToolPrefs().textLineColor;
                                        break;
                                case Line:
                                        m_lineColor = m_Doc->itemToolPrefs().lineColor;
                                        break;
                                case PolyLine:
                                case Polygon:
                                case ImageFrame:
                                case LatexFrame:
                                case OSGFrame:
                                case RegularPolygon:
                                case Arc:
                                case Spiral:
                                        m_lineColor = m_Doc->itemToolPrefs().shapeLineColor;
                                        break;
                                default:
                                        break;
                        }
                }
                if (!m_Doc->PageColors.contains(m_lineColor))
                        m_lineColor = m_Doc->itemToolPrefs().shapeLineColor;
                const ScColor& col = m_Doc->PageColors[m_lineColor];
                m_strokeQColor = ScColorEngine::getShadeColorProof(col, m_Doc, m_lineShade);
        }
        if (m_Doc->viewAsPreview)
        {
                VisionDefectColor defect;
                m_strokeQColor = defect.convertDefect(m_strokeQColor, m_Doc->previewVisual);
        }
}

void PageItem::setFillQColor()
{
        if (m_fillColor != CommonStrings::None)
        {
                if (!m_Doc->PageColors.contains(m_fillColor))
                {
                        switch (itemType())
                        {
                                case ImageFrame:
                                case LatexFrame:
                                case OSGFrame:
                                        m_fillColor = m_Doc->itemToolPrefs().imageFillColor;
                                        break;
                                case TextFrame:
                                case PathText:
                                        m_fillColor = m_Doc->itemToolPrefs().textFillColor;
                                        break;
                                case Line:
                                case PolyLine:
                                case Polygon:
                                case RegularPolygon:
                                case Arc:
                                case Spiral:
                                        m_fillColor = m_Doc->itemToolPrefs().shapeFillColor;
                                        break;
                                default:
                                        break;
                        }
                }
                const ScColor& col = m_Doc->PageColors[m_fillColor];
                m_fillQColor = ScColorEngine::getShadeColorProof(col, m_Doc, m_fillShade);
        }
        if (m_Doc->viewAsPreview)
        {
                VisionDefectColor defect;
                m_fillQColor = defect.convertDefect(m_fillQColor, m_Doc->previewVisual);
        }
}

void PageItem::setHatchParameters(int mode, double distance, double angle, bool useBackground, const QString& background, const QString& foreground)
{
        hatchType = mode;
        hatchDistance = distance;
        hatchAngle = angle;
        hatchUseBackground = useBackground;
        hatchBackground = background;
        hatchForeground = foreground;
        if (background != CommonStrings::None)
        {
                if (!m_Doc->PageColors.contains(background))
                        hatchBackgroundQ = QColor();
                else
                {
                        const ScColor& col = m_Doc->PageColors[background];
                        hatchBackgroundQ = ScColorEngine::getShadeColorProof(col, m_Doc, 100);
                        if (m_Doc->viewAsPreview)
                        {
                                VisionDefectColor defect;
                                hatchBackgroundQ = defect.convertDefect(hatchBackgroundQ, m_Doc->previewVisual);
                        }
                }
        }
        if (foreground != CommonStrings::None)
        {
                if (!m_Doc->PageColors.contains(foreground))
                        hatchForegroundQ = QColor();
                else
                {
                        const ScColor& col = m_Doc->PageColors[foreground];
                        hatchForegroundQ = ScColorEngine::getShadeColorProof(col, m_Doc, 100);
                        if (m_Doc->viewAsPreview)
                        {
                                VisionDefectColor defect;
                                hatchForegroundQ = defect.convertDefect(hatchForegroundQ, m_Doc->previewVisual);
                        }
                }
        }
}

void PageItem::setLineTransparency(double newTransparency)
{
        if (m_lineTransparency == newTransparency)
                return; // nothing to do -> return
        if (UndoManager::undoEnabled())
        {
                SimpleState *ss = new SimpleState(Um::LineTransparency,
                                                                                  QString(Um::FromTo).arg(m_lineTransparency).arg(newTransparency),
                                                                                  Um::ITransparency);
                ss->set("LINE_TRANSPARENCY");
                ss->set("OLD_TP", m_lineTransparency);
                ss->set("NEW_TP", newTransparency);
                undoManager->action(this, ss);
        }
        m_lineTransparency = newTransparency;
}

void PageItem::setLineBlendmode(int newBlendmode)
{
        if (m_lineBlendMode == newBlendmode)
                return; // nothing to do -> return
        if (UndoManager::undoEnabled())
        {
                SimpleState *ss = new SimpleState(Um::BlendMode, nullptr, Um::IGroup);
                ss->set("LINEBLENDMODE", newBlendmode);
                ss->set("LINEBLENDMODE_OLD", m_lineBlendMode);
                undoManager->action(this, ss);
        }
        m_lineBlendMode = newBlendmode;
}

void PageItem::setLineStyle(Qt::PenStyle newStyle)
{
        if (PLineArt == newStyle)
                return; // nothing to do -> return
        if (UndoManager::undoEnabled())
        {
                SimpleState *ss = new SimpleState(Um::LineStyle, QString(), Um::ILineStyle);
                ss->set("LINE_STYLE");
                ss->set("OLD_STYLE", static_cast<int>(PLineArt));
                ss->set("NEW_STYLE", static_cast<int>(newStyle));
                undoManager->action(this, ss);
        }
        PLineArt = newStyle;
}

void PageItem::setLineWidth(double newWidth)
{
        if ((m_lineWidth == newWidth) || (isGroup()))
                return; // nothing to do -> return
        if (UndoManager::undoEnabled())
        {
                SimpleState *ss = new SimpleState(Um::LineWidth,
                                                QString(Um::FromTo).arg(m_lineWidth).arg(newWidth),Um::ILineStyle);
                ss->set("LINE_WIDTH");
                ss->set("OLD_LINEWIDTH", m_lineWidth);
                ss->set("NEW_LINEWIDTH", newWidth);
                undoManager->action(this, ss);
        }
        m_oldLineWidth=m_lineWidth;
        m_lineWidth = newWidth;
}

void PageItem::setLineEnd(Qt::PenCapStyle newStyle)
{
        if (PLineEnd == newStyle)
                return; // nothing to do -> return
        if (UndoManager::undoEnabled())
        {
                SimpleState *ss = new SimpleState(Um::LineEnd, QString(), Um::ILineStyle);
                ss->set("LINE_END");
                ss->set("OLD_STYLE", static_cast<int>(PLineEnd));
                ss->set("NEW_STYLE", static_cast<int>(newStyle));
                undoManager->action(this, ss);
        }
        PLineEnd = newStyle;
}

void PageItem::setLineJoin(Qt::PenJoinStyle newStyle)
{
        if (PLineJoin == newStyle)
                return; // nothing to do -> return
        if (UndoManager::undoEnabled())
        {
                SimpleState *ss = new SimpleState(Um::LineJoin, QString(), Um::ILineStyle);
                ss->set("LINE_JOIN");
                ss->set("OLD_STYLE", static_cast<int>(PLineJoin));
                ss->set("NEW_STYLE", static_cast<int>(newStyle));
                undoManager->action(this, ss);
        }
        PLineJoin = newStyle;
}

void PageItem::setCustomLineStyle(const QString& newStyle)
{
        if (NamedLStyle == newStyle)
                return; // nothing to do -> return
        if (UndoManager::undoEnabled())
        {
                QString oldStyle = NamedLStyle.isEmpty() ? Um::NoStyle : NamedLStyle;
                QString nStyle   = newStyle.isEmpty() ? Um::NoStyle : newStyle;
                QString action   = newStyle.isEmpty() ? Um::NoLineStyle : Um::CustomLineStyle;
                SimpleState *ss = new SimpleState(action, QString(Um::FromTo).arg(oldStyle, nStyle), Um::ILineStyle);
                ss->set("CUSTOM_LINE_STYLE");
                ss->set("OLD_STYLE", NamedLStyle);
                ss->set("NEW_STYLE", newStyle);
                undoManager->action(this, ss);
        }
        NamedLStyle = newStyle;
}

void PageItem::setStartArrowIndex(int newIndex)
{
        if (m_startArrowIndex == newIndex)
                return; // nothing to do -> return
        if (UndoManager::undoEnabled())
        {
                SimpleState *ss = new SimpleState(Um::StartArrow, QString(), Um::IArrow);
                ss->set("START_ARROW");
                ss->set("OLD_INDEX", m_startArrowIndex);
                ss->set("NEW_INDEX", newIndex);
                undoManager->action(this, ss);
        }
        m_startArrowIndex = newIndex;
}

void PageItem::setEndArrowIndex(int newIndex)
{
        if (m_endArrowIndex == newIndex)
                return; // nothing to do -> return
        if (UndoManager::undoEnabled())
        {
                SimpleState *ss = new SimpleState(Um::EndArrow, QString(), Um::IArrow);
                ss->set("END_ARROW");
                ss->set("OLD_INDEX", m_endArrowIndex);
                ss->set("NEW_INDEX", newIndex);
                undoManager->action(this, ss);
        }
        m_endArrowIndex = newIndex;
}

void PageItem::setStartArrowScale(int newScale)
{
        if (m_startArrowScale == newScale)
                return; // nothing to do -> return
        if (UndoManager::undoEnabled())
        {
                SimpleState *ss = new SimpleState(Um::StartArrowScale, QString(), Um::IArrow);
                ss->set("START_ARROWSCALE");
                ss->set("OLD_SCALE", m_startArrowScale);
                ss->set("NEW_SCALE", newScale);
                undoManager->action(this, ss);
        }
        m_startArrowScale = newScale;
}

void PageItem::setEndArrowScale(int newScale)
{
        if (m_endArrowScale == newScale)
                return; // nothing to do -> return
        if (UndoManager::undoEnabled())
        {
                SimpleState *ss = new SimpleState(Um::EndArrowScale, QString(), Um::IArrow);
                ss->set("END_ARROWSCALE");
                ss->set("OLD_SCALE", m_endArrowScale);
                ss->set("NEW_SCALE", newScale);
                undoManager->action(this, ss);
        }
        m_endArrowScale = newScale;
}

void PageItem::setImageFlippedH(bool flipped)
{
        if (flipped != m_ImageIsFlippedH)
                flipImageH();
}

void PageItem::flipImageH()
{
        if (UndoManager::undoEnabled())
        {
                SimpleState *ss = new SimpleState(Um::FlipH, nullptr, Um::IFlipH);
                ss->set("IMAGEFLIPH");
                undoManager->action(this, ss);
        }
        m_ImageIsFlippedH = !m_ImageIsFlippedH;
}

void PageItem::setImageFlippedV(bool flipped)
{
        if (flipped != m_ImageIsFlippedV)
                flipImageV();
}

void PageItem::flipImageV()
{
        if (UndoManager::undoEnabled())
        {
                SimpleState *ss = new SimpleState(Um::FlipV, nullptr, Um::IFlipV);
                ss->set("IMAGEFLIPV");
                undoManager->action(this, ss);
        }
        m_ImageIsFlippedV = !m_ImageIsFlippedV;
}

void PageItem::setImageScalingMode(bool freeScale, bool keepRatio)
{
        if (ScaleType == freeScale && AspectRatio == keepRatio)
                return;
        if (UndoManager::undoEnabled())
        {
                QString from = ScaleType ? Um::FreeScaling : Um::FrameSize;
                from += ", ";
                from += AspectRatio ? Um::KeepRatio : Um::BreakRatio;
                QString to = freeScale ? Um::FreeScaling : Um::FrameSize;
                to += ", ";
                to += keepRatio ? Um::KeepRatio : Um::BreakRatio;
                SimpleState *ss = new SimpleState(Um::ImageScaling, QString(Um::FromTo).arg(from, to), Um::IImageScaling);
                ss->set("SCALE_MODE");
                if (freeScale != ScaleType)
                {
                        ss->set("SCALE_TYPE", freeScale);
                        if (!freeScale)
                        {
                                //if switching from free scaling to frame size
                                //in undo must be offset and scale saved
                                ss->set("OLD_IMAGEXOFFSET", m_imageXOffset);
                                ss->set("OLD_IMAGEYOFFSET", m_imageYOffset);
                                ss->set("OLD_IMAGEXSCALE", m_imageXScale);
                                ss->set("OLD_IMAGEYSCALE", m_imageYScale);
                        }
                }
                if (keepRatio != AspectRatio)
                        ss->set("ASPECT_RATIO", keepRatio);
                undoManager->action(this, ss);
        }
        ScaleType = freeScale;
        AspectRatio = keepRatio;
        adjustPictScale();
        update();
}

void PageItem::setOverprint(bool val)
{
        if (doOverprint == val)
                return;

        if (UndoManager::undoEnabled())
        {
                SimpleState *ss = new SimpleState(Um::Overprint, nullptr, Um::IGroup);
                ss->set("OVERPRINT", val);
                undoManager->action(this, ss);
        }
        doOverprint = val;
}

void PageItem::setHasSoftShadow(bool val)
{
        if (m_hasSoftShadow == val)
                return;

        if (UndoManager::undoEnabled())
        {
                SimpleState *ss = new SimpleState(Um::SoftShadow, nullptr, Um::IGroup);
                ss->set("SOFT_SHADOW");
                ss->set("NEW_VALUE", val);
                ss->set("OLD_VALUE", m_hasSoftShadow);
                undoManager->action(this, ss);
        }
        m_hasSoftShadow = val;
}

void PageItem::setSoftShadowColor(const QString &val)
{
        if (m_softShadowColor == val)
                return;

        if (UndoManager::undoEnabled())
        {
                SimpleState *ss = new SimpleState(Um::SoftShadowColor, nullptr, Um::IGroup);
                ss->set("SOFT_SHADOW_COLOR");
                ss->set("NEW_VALUE", val);
                ss->set("OLD_VALUE", m_softShadowColor);
                undoManager->action(this, ss);
        }
        m_softShadowColor = val;
}

void PageItem::setSoftShadowShade(int val)
{
        if (m_softShadowShade == val)
                return;

        if (UndoManager::undoEnabled())
        {
                SimpleState *ss = new SimpleState(Um::SoftShadowShade, nullptr, Um::IGroup);
                ss->set("SOFT_SHADOW_SHADE");
                ss->set("NEW_VALUE", val);
                ss->set("OLD_VALUE", m_softShadowShade);
                undoManager->action(this, ss);
        }
        m_softShadowShade = val;
}

void PageItem::setSoftShadowBlurRadius(double val)
{
        if (m_softShadowBlurRadius == val)
                return;

        if (UndoManager::undoEnabled())
        {
                SimpleState *ss = new SimpleState(Um::SoftShadowBlurRadius, nullptr, Um::IGroup);
                ss->set("SOFT_SHADOW_BLUR_RADIUS");
                ss->set("NEW_VALUE", val);
                ss->set("OLD_VALUE", m_softShadowBlurRadius);
                undoManager->action(this, ss);
        }
        m_softShadowBlurRadius = val;
}

void PageItem::setSoftShadowXOffset(double val)
{
        if (m_softShadowXOffset == val)
                return;

        if (UndoManager::undoEnabled())
        {
                SimpleState *ss = new SimpleState(Um::SoftShadowXOffset, nullptr, Um::IGroup);
                ss->set("SOFT_SHADOW_XOFFSET");
                ss->set("NEW_VALUE", val);
                ss->set("OLD_VALUE", m_softShadowXOffset)