Subversion Repositories Scribus

Rev

Rev 12141 | Rev 12795 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

/*
For general Scribus (>=1.3.2) copyright and licensing information please refer
to the COPYING file provided with the program. Following this notice may exist
a copyright and/or license notice that predates the release of Scribus 1.3.2
for which a new license (GPL+exception) is in place.
*/

#include "scpreview.h"
#include <QDomDocument>
#include <QMap>
#include <QPainter>
#include <QRect>
#include <QImage>
#include <QRegion>
#include <QRegExp>
#include <QFileInfo>
#include <QBitmap>
#include <QDir>
#include <QList>
#include <QPolygon>
#include <QTextStream>
#include <QPixmap>
#include <cmath>
#include <cstdlib>

#include "cmsettings.h"
#include "missing.h"
#include "sccolor.h"
#include "scribus.h"
#include "scribuscore.h"
#include "splash.h"
#include "util.h"
#include "util_math.h"
#include "prefsmanager.h"
#include "scpainter.h"
#include "commonstrings.h"
#include "sccolorengine.h"


using namespace std;


ScPreview::ScPreview()
{
        prefsManager = PrefsManager::instance();
        Farben.clear();
        MLineStyles.clear();
        Segments.clear();
}

QPixmap ScPreview::createPreview(QString data)
{
        int a;
        struct CopyPasteBuffer OB;
        ScText *hg, *hl;
        QList<ScText*> Ptexti;
        ScColor lf = ScColor();
        QFont fo;
        QMap<QString,QString> DoFonts;
        QMap<int,int> arrowID;
        QString tmpf, tmpx, tmp2, tmp3;
        int x, y, zae;
        double xf, yf, asce, chs;
        FPoint gv;
        int currItem, fillBlendmode, strokeBlendmode;
        QPolygon cl;
        QColor tmpfa;
        QString chstr;
        double CurY, EndX, CurX, wide, rota, wid;
        QList<ArrowDesc> arrowStyles;
        QStack<int> groupStack;
        arrowStyles = prefsManager->appPrefs.arrowStyles;
        QDomDocument docu("scridoc");
        docu.setContent(data);
        QDomElement elem=docu.documentElement();
        if ((elem.tagName() != "SCRIBUSELEM") && (elem.tagName() != "SCRIBUSELEMUTF8"))
        {
                QPixmap tmp = QPixmap(0, 0);
                return tmp;
        }
        double GrX = elem.attribute("XP").toDouble();
        double GrY = elem.attribute("YP").toDouble();
        double GrW = elem.attribute("W").toDouble();
        double GrH = elem.attribute("H").toDouble();
        double pmmax = 60 / qMax(GrW+50, GrH+50);
        QImage tmp = QImage(static_cast<int>(GrW)+50, static_cast<int>(GrH)+50, QImage::Format_ARGB32);
        tmp.fill( qRgba(255, 255, 255, 0) );
        ScPainter *pS = new ScPainter(&tmp, tmp.width(), tmp.height(), 1.0, 0);
        pS->beginLayer(1.0, 0);
        pS->translate(25,25);
        QDomNode DOC=elem.firstChild();
        DoFonts.clear();
        while(!DOC.isNull())
        {
                QDomElement pg=DOC.toElement();
                if(pg.tagName()=="Arrows")
                {
                        struct ArrowDesc arrow;
                        double xa, ya;
                        arrow.name = pg.attribute("Name");
                        QString tmp = pg.attribute("Points");
                        QTextStream fp(&tmp, QIODevice::ReadOnly);
                        for (uint cx = 0; cx < pg.attribute("NumPoints").toUInt(); ++cx)
                        {
                                fp >> xa;
                                fp >> ya;
                                arrow.points.addPoint(xa, ya);
                        }
                        arrowStyles.append(arrow);
                        arrowID.insert(pg.attribute("Index").toInt(), arrowStyles.count());
                }
                if(pg.tagName()=="FONT")
                {
                        tmpf = GetAttr(&pg, "NAME");
                        if ((!prefsManager->appPrefs.AvailFonts.contains(tmpf)) || (!prefsManager->appPrefs.AvailFonts[tmpf].usable()))
                        {
                                if ((!prefsManager->appPrefs.GFontSub.contains(tmpf)) || (!prefsManager->appPrefs.AvailFonts[prefsManager->appPrefs.GFontSub[tmpf]].usable()))
                                {
                                        ScCore->showSplash(false);
                                        MissingFont *dia = new MissingFont(0, tmpf, 0);
                                        dia->exec();
                                        tmpf = dia->getReplacementFont();
                                        delete dia;
                                        ScCore->showSplash(true);
                                        prefsManager->appPrefs.GFontSub[pg.attribute("NAME")] = tmpf;
                                }
                                else
                                        tmpf = prefsManager->appPrefs.GFontSub[tmpf];
                        }
                        if (!DoFonts.contains(tmpf))
                        {
//                              FT_Face face;
//                              error = FT_New_Face( library, prefsManager->appPrefs.AvailFonts[tmpf].fontFilePath(), prefsManager->appPrefs.AvailFonts[tmpf].faceIndex(), &face );
                                if ( prefsManager->appPrefs.AvailFonts[tmpf].usable() )
                                        tmpf = prefsManager->appPrefs.toolSettings.defFont;
/*                              if (prefsManager->appPrefs.AvailFonts[tmpf]->ReadMetrics()) {
//already done in ScFonts::addScalaableFont():
//                                      prefsManager->appPrefs.AvailFonts[tmpf]->CharWidth[13] = 0;
                                }
                                else
                                {
                                        tmpf = prefsManager->appPrefs.toolSettings.defFont;
//                                      prefsManager->appPrefs.AvailFonts[tmpf]->ReadMetrics();
//already done in ScFonts::addScalaableFont():
//                                      prefsManager->appPrefs.AvailFonts[tmpf]->CharWidth[13] = 0;
                                }
*/

                        }
//                      fo = prefsManager->appPrefs.AvailFonts[tmpf]->Font;
//                      fo.setPointSize(12);
                        DoFonts[GetAttr(&pg, "NAME")] = tmpf;
//                      DoFonts2[GetAttr(&pg, "NAME")] = fo;
                }
                if(pg.tagName()=="COLOR")
                {
                        if (pg.hasAttribute("CMYK"))
                                lf.setNamedColor(GetAttr(&pg, "CMYK"));
                        else
                                lf.fromQColor(QColor(GetAttr(&pg, "RGB")));
                        Farben[GetAttr(&pg, "NAME")] = lf;
                }
                if(pg.tagName()=="MultiLine")
                {
                        multiLine ml;
                        QDomNode MuLn = DOC.firstChild();
                        while(!MuLn.isNull())
                        {
                                QDomElement MuL = MuLn.toElement();
                                struct SingleLine sl;
                                sl.Color = MuL.attribute("Color");
                                sl.Dash = MuL.attribute("Dash").toInt();
                                sl.LineEnd = MuL.attribute("LineEnd").toInt();
                                sl.LineJoin = MuL.attribute("LineJoin").toInt();
                                sl.Shade = MuL.attribute("Shade").toInt();
                                sl.Width = MuL.attribute("Width").toDouble();
                                ml.push_back(sl);
                                MuLn = MuLn.nextSibling();
                        }
                        if (!MLineStyles.contains(pg.attribute("Name")))
                                MLineStyles.insert(pg.attribute("Name"), ml);
                }
                DOC=DOC.nextSibling();
        }
        DOC=elem.firstChild();
        currItem = -1;
        while(!DOC.isNull())
        {
                QDomElement pg=DOC.toElement();
                if(pg.tagName()=="ITEM")
                {
                        currItem++;
                        QString CurDirP = QDir::currentPath();
                        QDir::setCurrent(QDir::homePath());
                        Segments.clear();
                        // TODO: Nicer conversion
                        OB.PType = static_cast<PageItem::ItemType>(pg.attribute("PTYPE").toInt());
                        OB.Xpos = pg.attribute("XPOS").toDouble() - GrX;
                        OB.Ypos = pg.attribute("YPOS").toDouble() - GrY;
                        OB.Width = pg.attribute("WIDTH").toDouble();
                        OB.Height = pg.attribute("HEIGHT").toDouble();
                        OB.RadRect = pg.attribute("RADRECT", "0").toDouble();
                        OB.ClipEdited = pg.attribute("CLIPEDIT", "0").toInt();
                        OB.FrameType = pg.attribute("FRTYPE", "0").toInt();
                        OB.Pwidth = pg.attribute("PWIDTH").toDouble();
                        OB.Pcolor = pg.attribute("PCOLOR");
                        OB.Pcolor2 = pg.attribute("PCOLOR2");
                        OB.NamedLStyle = pg.attribute("NAMEDLST", "");
                        if (!MLineStyles.contains(OB.NamedLStyle))
                                OB.NamedLStyle = "";
                        OB.Shade = pg.attribute("SHADE").toInt();
                        OB.Shade2 = pg.attribute("SHADE2").toInt();
                        OB.TxtFill = pg.attribute("TXTFILL", "Black");
                        OB.TxtStroke = pg.attribute("TXTSTROKE", CommonStrings::None);
                        OB.ShTxtFill = pg.attribute("TXTFILLSH", "100").toInt();
                        OB.ShTxtStroke = pg.attribute("TXTSTRSH", "100").toInt();
                        OB.TxtScale = qRound(pg.attribute("TXTSCALE", "100").toDouble() * 10);
                        OB.TxtScaleV = qRound(pg.attribute("TXTSCALEV", "100").toDouble() * 10);
                        OB.TxTBase = qRound(pg.attribute("TXTBASE", "0").toDouble() * 10);
                        OB.TxTStyle = pg.attribute("TXTSTYLE", "0").toInt();
                        OB.GrType = pg.attribute("GRTYP", "0").toInt();
                        OB.fill_gradient.clearStops();
                        if (OB.GrType != 0)
                        {
                                OB.GrStartX = pg.attribute("GRSTARTX", "0.0").toDouble();
                                OB.GrStartY = pg.attribute("GRSTARTY", "0.0").toDouble();
                                OB.GrEndX = pg.attribute("GRENDX", "0.0").toDouble();
                                OB.GrEndY = pg.attribute("GRENDY", "0.0").toDouble();
                                OB.GrColor = pg.attribute("GRCOLOR","");
                                if (!OB.GrColor.isEmpty())
                                {
                                        OB.GrColor2 = pg.attribute("GRCOLOR2","");
                                        OB.GrShade = pg.attribute("GRSHADE", "100").toInt();
                                        OB.GrShade2 = pg.attribute("GRSHADE2", "100").toInt();
                                }
                        }
                        OB.Rot = pg.attribute("ROT").toDouble();
                        OB.PLineArt = Qt::PenStyle(pg.attribute("PLINEART").toInt());
                        OB.PLineEnd = Qt::PenCapStyle(pg.attribute("PLINEEND", "0").toInt());
                        OB.PLineJoin = Qt::PenJoinStyle(pg.attribute("PLINEJOIN", "0").toInt());
                        OB.LineSp = pg.attribute("LINESP").toDouble();
                        OB.ExtraV = static_cast<int>(pg.attribute("EXTRAV", "0").toDouble()); // temporary compiler silencing
                        OB.LocalScX = pg.attribute("LOCALSCX").toDouble();
                        OB.LocalScY = pg.attribute("LOCALSCY").toDouble();
                        OB.LocalX = pg.attribute("LOCALX").toDouble();
                        OB.LocalY = pg.attribute("LOCALY").toDouble();
                        OB.PicArt = pg.attribute("PICART").toInt();
                        OB.flippedH = pg.attribute("FLIPPEDH").toInt();
                        OB.flippedV = pg.attribute("FLIPPEDV").toInt();
                        OB.ScaleType = pg.attribute("SCALETYPE", "1").toInt();
                        OB.AspectRatio = pg.attribute("RATIO", "0").toInt();
                        OB.isPrintable = pg.attribute("PRINTABLE").toInt();
                        OB.isBookmark = false;
                        OB.m_isAnnotation = pg.attribute("ANNOTATION", "0").toInt();
                        if (pg.attribute("TRANSPARENT", "0").toInt() == 1)
                                OB.Pcolor = CommonStrings::None;
                        //OB.Textflow = pg.attribute("TEXTFLOW").toInt();
                        //OB.Textflow2 = pg.attribute("TEXTFLOW2", "0").toInt();
                        if ( pg.hasAttribute("TEXTFLOWMODE") )
                                OB.TextflowMode = (PageItem::TextFlowMode) pg.attribute("TEXTFLOWMODE", "0").toInt();
                        else if ( pg.attribute("TEXTFLOW").toInt() )
                        {
                                if (pg.attribute("TEXTFLOW2", "0").toInt())
                                        OB.TextflowMode = PageItem::TextFlowUsesBoundingBox;
                                else if (pg.attribute("TEXTFLOW3", "0").toInt())
                                        OB.TextflowMode = PageItem::TextFlowUsesContourLine;
                                else
                                        OB.TextflowMode = PageItem::TextFlowUsesFrameShape;    
                        }
                        else
                                OB.TextflowMode = PageItem::TextFlowDisabled;
                        OB.Extra = pg.attribute("EXTRA").toDouble();
                        OB.TExtra = pg.attribute("TEXTRA", "1").toDouble();
                        OB.BExtra = pg.attribute("BEXTRA", "1").toDouble();
                        OB.RExtra = pg.attribute("REXTRA", "1").toDouble();
                        OB.PoShow = pg.attribute("PTLSHOW", "0").toInt();
                        OB.BaseOffs = pg.attribute("BASEOF", "0").toDouble();
                        OB.textAlignment = pg.attribute("ALIGN", "0").toInt();
                        OB.IFont = DoFonts[pg.attribute("IFONT")];
                        OB.ISize = qRound(pg.attribute("ISIZE", "12").toDouble() * 10.0);
                        if (OB.PType == PageItem::LatexFrame) {
                                OB.Pfile = pg.attribute("LATEXTEMPFILE", "");
                                //Hack to create a preview for latex frames
                        } else {
                                OB.Pfile = pg.attribute("PFILE");
                        }
                        OB.Pfile2 = pg.attribute("PFILE2","");
                        OB.Pfile3 = pg.attribute("PFILE3","");
                        OB.IProfile = pg.attribute("PRFILE","");
                        OB.EmProfile = pg.attribute("EPROF","");
                        OB.IRender = pg.attribute("IRENDER", "1").toInt();
                        OB.UseEmbedded = pg.attribute("EMBEDDED", "1").toInt();
                        OB.Locked = static_cast<bool>(pg.attribute("LOCK", "0").toInt());
                        OB.Reverse = static_cast<bool>(pg.attribute("REVERS", "0").toInt());
                        OB.Transparency = pg.attribute("TransValue", "0.0").toDouble();
                        if (pg.hasAttribute("TransValueS"))
                                OB.TranspStroke = pg.attribute("TransValueS", "0.0").toDouble();
                        else
                                OB.TranspStroke = OB.Transparency;
                        fillBlendmode = pg.attribute("TransBlend", "0").toInt();
                        strokeBlendmode = pg.attribute("TransBlendS", "0").toInt();
                        if (pg.hasAttribute("NUMCLIP"))
                        {
                                OB.Clip.resize(pg.attribute("NUMCLIP").toUInt());
                                tmpx = pg.attribute("CLIPCOOR");
                                QTextStream f(&tmpx, QIODevice::ReadOnly);
                                for (uint c=0; c<pg.attribute("NUMCLIP").toUInt(); ++c)
                                {
                                        f >> x;
                                        f >> y;
                                        OB.Clip.setPoint(c, x, y);
                                }
                        }
                        else
                                OB.Clip.resize(0);
                        if (pg.hasAttribute("NUMPO"))
                        {
                                OB.PoLine.resize(pg.attribute("NUMPO").toUInt());
                                tmpx = pg.attribute("POCOOR");
                                QTextStream fp(&tmpx, QIODevice::ReadOnly);
                                for (uint cx=0; cx<pg.attribute("NUMPO").toUInt(); ++cx)
                                {
                                        fp >> xf;
                                        fp >> yf;
                                        OB.PoLine.setPoint(cx, xf, yf);
                                }
                        }
                        else
                                OB.PoLine.resize(0);
                        OB.Groups.clear();
                        if (OB.Clip.size() == 0)
                                OB.Clip = FlattenPath(OB.PoLine, Segments);
                        tmpx = "";
                        QDomNode IT=DOC.firstChild();
                        while(!IT.isNull())
                        {
                                QDomElement it=IT.toElement();
                                if (it.tagName()=="CSTOP")
                                {
                                        QString name = it.attribute("NAME");
                                        double ramp = it.attribute("RAMP", "0.0").toDouble();
                                        int shade = it.attribute("SHADE", "100").toInt();
                                        SetQColor(&tmpfa, name, shade);
                                        OB.fill_gradient.addStop(tmpfa, ramp, 0.5, 1.0, name, shade);
                                }
                                if (it.tagName()=="ITEXT")
                                {
                                        tmp2 = it.attribute("CH");
                                        tmp2.replace(QRegExp("\r"), QChar(5));
                                        tmp2.replace(QRegExp("\n"), QChar(5));
                                        tmp3 = "\t" + DoFonts[it.attribute("CFONT", OB.IFont)] + "\t";
                                        tmp3 += it.attribute("CSIZE" , QString::number(OB.ISize)) + "\t";
                                        tmp3 += it.attribute("CCOLOR", OB.TxtFill) + "\t";
//                                      tmp3 += it.attribute("CEXTRA") + "\t";
                                        tmp3 += "0\t";
                                        tmp3 += it.attribute("CSHADE", QString::number(OB.ShTxtFill)) + "\t";
                                        tmp3 += it.attribute("CSTYLE") + "\t";
                                        tmp3 += "0\t";
                                        tmp3 += it.attribute("CSTROKE",CommonStrings::None) + "\t";
                                        tmp3 += it.attribute("CSHADE2","100") + "\t";
                                        tmp3 += it.attribute("CSCALE","100") + "\n";
                                        for (int cxx=0; cxx<tmp2.length(); cxx++)
                                        {
                                                tmpx += tmp2.at(cxx)+tmp3;
                                        }
                                }
                                if (it.tagName()=="PARA")
                                {
                                        tmp2 = QChar(5);
                                        tmp3 = "\t" + DoFonts[it.attribute("FONT", OB.IFont)] + "\t";
                                        tmp3 += it.attribute("FONTSIZE" , QString::number(OB.ISize)) + "\t";
                                        tmp3 += it.attribute("FCOLOR", OB.TxtFill) + "\t";
                                        tmp3 += "0\t";
                                        tmp3 += it.attribute("FSHADE", QString::number(OB.ShTxtFill)) + "\t";
                                        tmp3 += it.attribute("CSTYLE") + "\t";
                                        tmp3 += "0\t";
                                        tmp3 += it.attribute("SCOLOR",CommonStrings::None) + "\t";
                                        tmp3 += it.attribute("SSHADE","100") + "\t";
                                        tmp3 += it.attribute("SCALEH","100") + "\n";
                                        tmpx += tmp2+tmp3;
                                }
                                IT=IT.nextSibling();
                        }
                        OB.itemText = tmpx;
                        if (!OB.itemText.isEmpty())
                        {
                                QTextStream t(&OB.itemText, QIODevice::ReadOnly);
                                QString cc;
#ifndef NLS_PROTO
                                while (!t.atEnd())
                                {
                                        cc = t.readLine();
                                        if (cc.isEmpty())
                                                continue;
                                        QStringList wt;
                                        QStringList::Iterator it;
                                        wt = cc.split("\t", QString::SkipEmptyParts);
                                        it = wt.begin();
                                        hg = new ScText;
                                        hg->ch = it->at(0);
                                        if (hg->ch == QChar(5))
                                                hg->ch = QChar(13);
                                        it++;
                                        hg->setFont(prefsManager->appPrefs.AvailFonts[*it]);
                                        it++;
                                        hg->setFontSize(qRound((*it).toDouble() * 10.0));
                                        it++;
                                        hg->setFillColor(*it);
                                        it++;
                                        hg->setTracking((*it).toInt());
                                        it++;
                                        hg->setFillShade((*it).toInt());
                                        it++;
                                        // Qt4 if (it == NULL)
                                        if (it == wt.end())
                                                hg->setFeatures(QStringList(CharStyle::INHERIT));
                                        else
                                                hg->setFeatures(static_cast<StyleFlag>((*it).toInt()).featureList());
                                        it++;
//                                      if (it == NULL)
//                                              hg->cab = 0;
//                                      else
//                                              hg->cab = (*it).toInt();
                                        it++;
                                        if (it == wt.end())
                                                hg->setStrokeColor(CommonStrings::None);
                                        else
                                                hg->setStrokeColor(*it);
                                        it++;
                                        if (it == wt.end())
                                                hg->setStrokeShade(100);
                                        else
                                                hg->setStrokeShade((*it).toInt());
                                        it++;
                                        if (it == wt.end())
                                                hg->setScaleH(100);
                                        else
                                                hg->setScaleH((*it).toInt());

                                        Ptexti.append(hg);
                                }
#endif
                        }
                        tmpx = GetAttr(&pg, "TEXTCOOR","0 0");
                        QTextStream ft(&tmpx, QIODevice::ReadOnly);
                        for (uint ct=0; ct<GetAttr(&pg, "NUMTEXT","0").toUInt(); ct++)
                        {
#ifndef NLS_PROTO
                                ft >> Ptexti.at(ct)->glyph.xoffset;
                                ft >> Ptexti.at(ct)->glyph.yoffset;
#endif
                        }
                        tmpx = "";
                        if ((OB.PType == 5) && (OB.Height != 0))
                        {
                                OB.Rot += atan2(OB.Height,OB.Width)*(180.0/M_PI);
                                OB.Width = sqrt(pow(OB.Width,2)+pow(OB.Height,2));
                                OB.Height = 0;
                                OB.Clip.setPoints(4, -1,-1, static_cast<int>(OB.Width+1),-1, static_cast<int>(OB.Width+1), static_cast<int>(OB.Height+1), -1, static_cast<int>(OB.Height+1));
                        }
                        OB.LayerNr = -1;
                        OB.startArrowIndex =  arrowID[pg.attribute("startArrowIndex", "0").toInt()];
                        OB.endArrowIndex =  arrowID[pg.attribute("endArrowIndex", "0").toInt()];
                        if(static_cast<bool>(pg.attribute("isGroupControl", "0").toInt()))
                        {
                                pS->save();
                                FPointArray cl = OB.PoLine.copy();
                                QMatrix mm;
                                mm.translate(OB.Xpos, OB.Ypos);
                                mm.rotate(static_cast<double>(OB.Rot));
                                cl.map( mm );
                                pS->beginLayer(1.0 - OB.Transparency, pg.attribute("TransBlend", "0").toInt(), &cl);
                                groupStack.push(pg.attribute("groupsLastItem", "0").toInt() + currItem);
                                DOC=DOC.nextSibling();
                                continue;
                        }
                        pS->save();
                        if (fillBlendmode != 0)
                                pS->beginLayer(1.0 - OB.Transparency, fillBlendmode);
                        else
                                pS->setBrushOpacity(1.0 - OB.Transparency);
                        pS->translate(OB.Xpos, OB.Ypos);
                        pS->rotate(static_cast<double>(OB.Rot));
                        if (OB.Pcolor != CommonStrings::None)
                        {
                                SetQColor(&tmpfa, OB.Pcolor, OB.Shade);
                                pS->setBrush(tmpfa);
                                pS->setFillMode(1);
                        }
                        else
                                pS->setFillMode(0);
                        if (OB.GrType != 0)
                        {
                                pS->setFillMode(2);
                                pS->fill_gradient.clearStops();
                                if ((!OB.GrColor.isEmpty()) && (!OB.GrColor2.isEmpty()))
                                {
                                        if (OB.GrType == 5)
                                        {
                                                if ((OB.GrColor != CommonStrings::None) && (!OB.GrColor.isEmpty()))
                                                        SetQColor(&tmpfa, OB.GrColor, OB.GrShade);
                                                pS->fill_gradient.addStop(tmpfa, 0.0, 0.5, 1.0);
                                                if ((OB.GrColor2 != CommonStrings::None) && (!OB.GrColor2.isEmpty()))
                                                        SetQColor(&tmpfa, OB.GrColor2, OB.GrShade2);
                                                pS->fill_gradient.addStop(tmpfa, 1.0, 0.5, 1.0);
                                        }
                                        else
                                        {
                                                if ((OB.GrColor2 != CommonStrings::None) && (!OB.GrColor2.isEmpty()))
                                                        SetQColor(&tmpfa, OB.GrColor2, OB.GrShade2);
                                                pS->fill_gradient.addStop(tmpfa, 0.0, 0.5, 1.0);
                                                if ((OB.GrColor != CommonStrings::None) && (!OB.GrColor.isEmpty()))
                                                        SetQColor(&tmpfa, OB.GrColor, OB.GrShade);
                                                pS->fill_gradient.addStop(tmpfa, 1.0, 0.5, 1.0);
                                        }
                                }
                                else
                                        pS->fill_gradient = OB.fill_gradient;
                                QMatrix grm;
                                grm.rotate(OB.Rot);
                                FPointArray gra;
                                switch (OB.GrType)
                                {
                                case 1:
                                        gra.setPoints(2, 0, 0, OB.Width, 0);
                                        gra.map(grm);
                                        pS->setGradient(VGradient::linear, gra.point(0), gra.point(1));
                                        break;
                                case 2:
                                        gra.setPoints(2, 0, 0, OB.Height, 0);
                                        grm.rotate(90);
                                        gra.map(grm);
                                        pS->setGradient(VGradient::linear, gra.point(0), gra.point(1));
                                        break;
                                case 3:
                                        gra.setPoints(2, 0, 0, OB.Width, OB.Height);
                                        gra.map(grm);
                                        pS->setGradient(VGradient::linear, gra.point(0), gra.point(1));
                                        break;
                                case 4:
                                        gra.setPoints(2, 0, OB.Height, OB.Width, 0);
                                        gra.map(grm);
                                        pS->setGradient(VGradient::linear, gra.point(0), gra.point(1));
                                        break;
                                case 5:
                                        if (OB.Width > OB.Height)
                                                gv = FPoint(OB.Width, OB.Height / 2.0);
                                        else
                                                gv = FPoint(OB.Width / 2.0, OB.Height);
                                        pS->setGradient(VGradient::radial, FPoint(OB.Width / 2.0,OB.Height / 2.0), gv, FPoint(OB.Width / 2.0,OB.Height / 2.0));
                                        break;
                                case 6:
                                        gra.setPoints(2, OB.GrStartX, OB.GrStartY, OB.GrEndX, OB.GrEndY);
                                        gra.map(grm);
                                        pS->setGradient(VGradient::linear, gra.point(0), gra.point(1));
                                        break;
                                }
                        }
                        if (OB.Pcolor2 != CommonStrings::None)
                        {
                                SetQColor(&tmpfa, OB.Pcolor2, OB.Shade2);
                                if ((OB.Pwidth == 0) && (OB.PType != 5))
                                        pS->setLineWidth(0);
                                else
                                        pS->setPen(tmpfa, OB.Pwidth, Qt::PenStyle(OB.PLineArt), Qt::PenCapStyle(OB.PLineEnd), Qt::PenJoinStyle(OB.PLineJoin));
                        }
                        else
                                pS->setLineWidth(0);
                        bool doStroke;
                        int mode;
                        doStroke = true;
                        switch (OB.PType)
                        {
                        case PageItem::ImageFrame:
                        case PageItem::LatexFrame:
                                if ((OB.Pcolor != CommonStrings::None) || (OB.GrType != 0))
                                {
                                        pS->setupPolygon(&OB.PoLine);
                                        pS->drawPolygon();
                                }
                                if (!OB.Pfile.isEmpty())
                                {
                                        QFileInfo fi = QFileInfo(OB.Pfile);
                                        if (fi.exists())
                                        {
                                                pS->setupPolygon(&OB.PoLine);
                                                pS->setClipPath();
                                                pS->save();
                                                if (OB.flippedH)
                                                {
                                                        pS->translate(OB.Width, 0);
                                                        pS->scale(-1, 1);
                                                }
                                                if (OB.flippedV)
                                                {
                                                        pS->translate(0, OB.Height);
                                                        pS->scale(1, -1);
                                                }
                                                ScImage pixm;
                                                CMSettings cms(0, "", 0);
                                                pixm.LoadPicture(OB.Pfile, 1, cms, false, false, ScImage::RGBData, 72); //FIXME: OB doesnt know about pagenr
                                                pS->scale(OB.LocalScX, OB.LocalScY);
                                                pS->translate(static_cast<int>(OB.LocalX), static_cast<int>(OB.LocalY));
                                                QImage img(pixm.qImage());
                                                pS->drawImage(&img);
                                                pS->restore();
                                        }
                                }
                                break;
                        case PageItem::TextFrame:
#ifndef NLS_PROTO
                                if (Ptexti.count() != 0)
                                {
                                        pS->save();
                                        if (OB.Pcolor != CommonStrings::None)
                                        {
                                                pS->setupPolygon(&OB.PoLine);
                                                pS->drawPolygon();
                                        }
                                        if (OB.flippedH)
                                        {
                                                pS->translate(OB.Width, 0);
                                                pS->scale(-1, 1);
                                        }
                                        if (OB.flippedV)
                                        {
                                                pS->translate(0, OB.Height);
                                                pS->scale(1, -1);
                                        }
                                        if ((OB.Width < 4) || (OB.Height < 4))
                                                break;
                                        for (int a = 0; a < Ptexti.count(); a++)
                                        {
                                                hl = Ptexti.at(a);
                                                if (hl->ch == QChar(13))
                                                        continue;
                                                chstr = hl->ch;
                                                chs = hl->fontSize();
                                                if (chs < 10)
                                                        continue;
                                                if (hl->effects() != ScStyle_Default)
                                                {
                                                        if (hl->effects() & 1)
                                                                chs = static_cast<int>(hl->fontSize() * prefsManager->appPrefs.typographicSettings.scalingSuperScript / 100);
                                                        if (hl->effects() & 2)
                                                                chs = static_cast<int>(hl->fontSize() * prefsManager->appPrefs.typographicSettings.scalingSubScript / 100);
                                                        if (hl->effects() & 64)
                                                        {
                                                                if (chstr.toUpper() != chstr)
                                                                {
                                                                        chs = static_cast<int>(hl->fontSize() * prefsManager->appPrefs.typographicSettings.valueSmallCaps / 100);
                                                                        chstr = chstr.toUpper();
                                                                }
                                                        }
                                                }
                                                mode = 0;
                                                if (hl->fillColor() != CommonStrings::None)
                                                {
                                                        SetQColor(&tmpfa, hl->fillColor(), hl->fillShade());
                                                        pS->setBrush(tmpfa);
                                                        mode = 2;
                                                }
                                                if (hl->strokeColor() != CommonStrings::None)
                                                {
                                                        SetQColor(&tmpfa, hl->strokeColor(), hl->strokeShade());
                                                        pS->setPen(tmpfa, 1, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin);
                                                        mode += 1;
                                                }
                                                DrawZeichenS(pS, hl->glyph.xoffset, hl->glyph.yoffset, chstr, hl->font().scName(), OB.Reverse, hl->effects(), mode, chs);
                                        }
                                        pS->restore();
                                }
                                break;
#endif
                        case PageItem::Line:
                                if (OB.NamedLStyle.isEmpty())
                                        pS->drawLine(FPoint(0, 0), FPoint(OB.Width, 0));
                                else
                                {
                                        multiLine ml = MLineStyles[OB.NamedLStyle];
                                        for (int it = ml.size()-1; it > -1; it--)
                                        {
                                                SetQColor(&tmpfa, ml[it].Color, ml[it].Shade);
                                                pS->setPen(tmpfa,
                                                           qMax(static_cast<int>(ml[it].Width), 1),
                                                           static_cast<Qt::PenStyle>(ml[it].Dash),
                                                           static_cast<Qt::PenCapStyle>(ml[it].LineEnd),
                                                           static_cast<Qt::PenJoinStyle>(ml[it].LineJoin));
                                                pS->drawLine(FPoint(0, 0), FPoint(OB.Width, 0));
                                        }
                                }
                                if (OB.startArrowIndex != 0)
                                {
                                        QMatrix arrowTrans;
                                        FPointArray arrow = arrowStyles.at(OB.startArrowIndex-1).points.copy();
                                        arrowTrans.translate(0, 0);
                                        arrowTrans.scale(OB.Pwidth, OB.Pwidth);
                                        arrowTrans.scale(-1,1);
                                        arrow.map(arrowTrans);
                                        pS->setBrush(pS->pen());
                                        pS->setLineWidth(0);
                                        pS->setFillMode(ScPainter::Solid);
                                        pS->setupPolygon(&arrow);
                                        pS->drawPolygon();
                                }
                                if (OB.endArrowIndex != 0)
                                {
                                        QMatrix arrowTrans;
                                        FPointArray arrow = arrowStyles.at(OB.endArrowIndex-1).points.copy();
                                        arrowTrans.translate(OB.Width, 0);
                                        arrowTrans.scale(OB.Pwidth, OB.Pwidth);
                                        arrow.map(arrowTrans);
                                        pS->setBrush(pS->pen());
                                        pS->setLineWidth(0);
                                        pS->setFillMode(ScPainter::Solid);
                                        pS->setupPolygon(&arrow);
                                        pS->drawPolygon();
                                }
                                doStroke = false;
                                break;
                        /* OBSOLETE Craig R 2005-02-06
                        case 1:
                        case 3:
                        */

                        case PageItem::ItemType1:
                        case PageItem::ItemType3:
                        case PageItem::Polygon:
                                pS->setupPolygon(&OB.PoLine);
                                pS->drawPolygon();
                                break;
                        case PageItem::PolyLine:
                                if (OB.PoLine.size() < 4)
                                        break;
                                if ((OB.Pcolor != CommonStrings::None) || (OB.GrType != 0))
                                {
                                        FPointArray cli;
                                        FPoint Start;
                                        bool firstp = true;
                                        for (uint n = 0; n < OB.PoLine.size()-3; n += 4)
                                        {
                                                if (firstp)
                                                {
                                                        Start = OB.PoLine.point(n);
                                                        firstp = false;
                                                }
                                                if (OB.PoLine.point(n).x() > 900000)
                                                {
                                                        cli.addPoint(OB.PoLine.point(n-2));
                                                        cli.addPoint(OB.PoLine.point(n-2));
                                                        cli.addPoint(Start);
                                                        cli.addPoint(Start);
                                                        cli.setMarker();
                                                        firstp = true;
                                                        continue;
                                                }
                                                cli.addPoint(OB.PoLine.point(n));
                                                cli.addPoint(OB.PoLine.point(n+1));
                                                cli.addPoint(OB.PoLine.point(n+2));
                                                cli.addPoint(OB.PoLine.point(n+3));
                                        }
                                        if (cli.size() > 2)
                                        {
                                                FPoint l1 = cli.point(cli.size()-2);
                                                cli.addPoint(l1);
                                                cli.addPoint(l1);
                                                cli.addPoint(Start);
                                                cli.addPoint(Start);
                                        }
                                        pS->setupPolygon(&cli);
                                        pS->fillPath();
                                }
                                pS->setupPolygon(&OB.PoLine, false);
                                if (OB.NamedLStyle.isEmpty())
                                        pS->strokePath();
                                else
                                {
                                        multiLine ml = MLineStyles[OB.NamedLStyle];
                                        for (int it = ml.size()-1; it > -1; it--)
                                        {
                                                SetQColor(&tmpfa, ml[it].Color, ml[it].Shade);
                                                pS->setPen(tmpfa, ml[it].Width,
                                                           static_cast<Qt::PenStyle>(ml[it].Dash),
                                                           static_cast<Qt::PenCapStyle>(ml[it].LineEnd),
                                                           static_cast<Qt::PenJoinStyle>(ml[it].LineJoin));
                                                pS->drawPolyLine();
                                        }
                                }
                                if (OB.startArrowIndex != 0)
                                {
                                        FPoint Start = OB.PoLine.point(0);
                                        for (uint xx = 1; xx < OB.PoLine.size(); xx += 2)
                                        {
                                                FPoint Vector = OB.PoLine.point(xx);
                                                if ((Start.x() != Vector.x()) || (Start.y() != Vector.y()))
                                                {
                                                        double r = atan2(Start.y()-Vector.y(),Start.x()-Vector.x())*(180.0/M_PI);
                                                        QMatrix arrowTrans;
                                                        FPointArray arrow = arrowStyles.at(OB.startArrowIndex-1).points.copy();
                                                        arrowTrans.translate(Start.x(), Start.y());
                                                        arrowTrans.rotate(r);
                                                        arrowTrans.scale(OB.Pwidth, OB.Pwidth);
                                                        arrow.map(arrowTrans);
                                                        pS->setBrush(pS->pen());
                                                        pS->setLineWidth(0);
                                                        pS->setFillMode(ScPainter::Solid);
                                                        pS->setupPolygon(&arrow);
                                                        pS->drawPolygon();
                                                        break;
                                                }
                                        }
                                }
                                if (OB.endArrowIndex != 0)
                                {
                                        FPoint End = OB.PoLine.point(OB.PoLine.size()-2);
                                        for (uint xx = OB.PoLine.size()-1; xx > 0; xx -= 2)
                                        {
                                                FPoint Vector = OB.PoLine.point(xx);
                                                if ((End.x() != Vector.x()) || (End.y() != Vector.y()))
                                                {
                                                        double r = atan2(End.y()-Vector.y(),End.x()-Vector.x())*(180.0/M_PI);
                                                        QMatrix arrowTrans;
                                                        FPointArray arrow = arrowStyles.at(OB.endArrowIndex-1).points.copy();
                                                        arrowTrans.translate(End.x(), End.y());
                                                        arrowTrans.rotate(r);
                                                        arrowTrans.scale(OB.Pwidth, OB.Pwidth);
                                                        arrow.map(arrowTrans);
                                                        pS->setBrush(pS->pen());
                                                        pS->setLineWidth(0);
                                                        pS->setFillMode(ScPainter::Solid);
                                                        pS->setupPolygon(&arrow);
                                                        pS->drawPolygon();
                                                        break;
                                                }
                                        }
                                }
                                doStroke = false;
                                break;
                        case PageItem::PathText:
#ifndef NLS_PROTO
                                if (!OB.PoShow)
                                        doStroke = false;
                                cl = FlattenPath(OB.PoLine, Segments);
                                CurX = OB.Extra;
                                if (Ptexti.count() != 0)
                                        CurX += Ptexti.at(0)->fontSize() * Ptexti.at(0)->tracking() / 10000.0;
                                zae = 0;
                                wid = sqrt(pow(cl.point(zae+1).x()-cl.point(zae).x(),2.0)+pow(cl.point(zae+1).y()-cl.point(zae).y(),2.0));
                                while (wid < 1)
                                {
                                        zae++;
                                        if (zae == cl.size()-1)
                                                goto PfadEnd;
                                        wid = sqrt(pow(cl.point(zae+1).x()-cl.point(zae).x(),2.0)+pow(cl.point(zae+1).y()-cl.point(zae).y(),2.0));
                                }
                                rota = xy2Deg(cl.point(zae+1).x()-cl.point(zae).x(),cl.point(zae+1).y()-cl.point(zae).y());
                                for (a = 0; a < Ptexti.count(); a++)
                                {
                                        CurY = 0;
                                        hl = Ptexti.at(a);
                                        chstr = hl->ch;
                                        if ((chstr == QChar(30)) || (chstr == QChar(13)))
                                                continue;
                                        if (hl->fillColor() != CommonStrings::None)
                                        {
                                                SetQColor(&tmpfa, hl->fillColor(), hl->fillShade());
                                                pS->setPen(tmpfa);
                                        }
                                        chs = hl->fontSize();
                                        asce = hl->font().ascent(hl->fontSize() / 10.0);
                                        int chst = hl->effects() & 127;
                                        if (chst != 0)
                                        {
                                                if (chst & 1)
                                                {
                                                        CurY -= asce * prefsManager->appPrefs.typographicSettings.valueSuperScript / 100;
                                                        chs = static_cast<int>(hl->fontSize() * prefsManager->appPrefs.typographicSettings.scalingSuperScript / 100);
                                                }
                                                if (chst & 2)
                                                {
                                                        CurY += asce * prefsManager->appPrefs.typographicSettings.valueSubScript / 100;
                                                        chs = static_cast<int>(hl->fontSize() * prefsManager->appPrefs.typographicSettings.scalingSubScript / 100);
                                                }
                                                if (chst & 64)
                                                {
                                                        if (chstr.toUpper() != chstr)
                                                        {
                                                                chs = static_cast<int>(hl->fontSize() * prefsManager->appPrefs.typographicSettings.valueSmallCaps / 100);
                                                                chstr = chstr.toUpper();
                                                        }
                                                }
                                        }
                                        wide = hl->font().charWidth(chstr[0], chs / 10.0);
                                        if ((CurX+(wide+chs * hl->tracking() / 10000.0)/2) >= wid)
                                        {
                                                if (zae < cl.size()-1)
                                                {
                                                        CurX = CurX - wid;
                                                        wid = 0;
                                                        EndX = CurX;
                                                        do
                                                        {
                                                                do
                                                                {
                                                                        zae++;
                                                                        if (zae == cl.size()-1)
                                                                                goto PfadEnd;
                                                                        wid = sqrt(pow(cl.point(zae+1).x()-cl.point(zae).x(),2.0)+pow(cl.point(zae+1).y()-cl.point(zae).y(),2.0));
                                                                        rota = xy2Deg(cl.point(zae+1).x()-cl.point(zae).x(),cl.point(zae+1).y()-cl.point(zae).y());
                                                                }
                                                                while (wid == 0);
                                                                EndX -= wid;
                                                        }
                                                        while (wid < EndX);
                                                        CurX = EndX + wid;
                                                }
                                                else
                                                        goto PfadEnd;
                                        }
                                        pS->save();
                                        pS->translate(cl.point(zae).x(), cl.point(zae).y());
                                        pS->rotate(rota);
                                        DrawZeichenS(pS, CurX+chs * hl->tracking() / 10000.0, CurY+OB.BaseOffs, chstr, hl->font().scName(), OB.Reverse, hl->effects(), 2, chs);
                                        pS->restore();
                                        CurX += wide+chs * hl->tracking() / 10000.0;
                                }
#endif
                        PfadEnd:        break;
                        case PageItem::Multiple:
                                Q_ASSERT(false);
                                break;
                        }
                        if (fillBlendmode != 0)
                                pS->endLayer();
                        if (doStroke)
                        {
                                if (strokeBlendmode != 0)
                                        pS->beginLayer(1.0 - OB.TranspStroke, strokeBlendmode);
                                else
                                        pS->setPenOpacity(1.0 - OB.TranspStroke);
                                if (OB.Pcolor2 != CommonStrings::None)
                                {
                                        SetQColor(&tmpfa, OB.Pcolor2, OB.Shade2);
                                        pS->setPen(tmpfa, OB.Pwidth, Qt::PenStyle(OB.PLineArt), Qt::PenCapStyle(OB.PLineEnd), Qt::PenJoinStyle(OB.PLineJoin));
                                        //                                      if (DashValues.count() != 0)
                                        //                                              pS->setDash(DashValues, DashOffset);
                                }
                                else
                                        pS->setLineWidth(0);
                                pS->setupPolygon(&OB.PoLine);
                                if (OB.NamedLStyle.isEmpty())
                                        pS->drawPolyLine();
                                else
                                {
                                        multiLine ml = MLineStyles[OB.NamedLStyle];
                                        for (int it = ml.size()-1; it > -1; it--)
                                        {
                                                SetQColor(&tmpfa, ml[it].Color, ml[it].Shade);
                                                pS->setPen(tmpfa, ml[it].Width,
                                                           static_cast<Qt::PenStyle>(ml[it].Dash),
                                                           static_cast<Qt::PenCapStyle>(ml[it].LineEnd),
                                                           static_cast<Qt::PenJoinStyle>(ml[it].LineJoin));
                                                pS->drawPolyLine();
                                        }
                                }
                                if (strokeBlendmode != 0)
                                        pS->endLayer();
                        }
                        pS->restore();
                        if (groupStack.count() != 0)
                        {
                                while (currItem == groupStack.top())
                                {
                                        pS->endLayer();
                                        pS->restore();
                                        groupStack.pop();
                                        if (groupStack.count() == 0)
                                                break;
                                }
                        }
                        QDir::setCurrent(CurDirP);
                }
                DOC=DOC.nextSibling();
        }
        pS->endLayer();
        pS->end();
        QImage tmpi = tmp.scaled(static_cast<int>(tmp.width()*pmmax), static_cast<int>(tmp.height()*pmmax), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
        QPixmap ret;
        ret=QPixmap::fromImage(tmpi);
        delete pS;
//      FT_Done_FreeType( library );
        return ret;
}

void ScPreview::SetQColor(QColor *tmp, const QString& farbe, double shad)
{
        *tmp = ScColorEngine::getShadeColorProof(Farben[farbe], NULL, shad);
}

void ScPreview::DrawZeichenS(ScPainter *p, double xco, double yco, QString ch, QString ZFo, bool Reverse, int Style, int mod, double Siz)
{
        if (mod == 0)
                return;
        QString ccx = ch;
        if (ccx == QChar(29))
                ccx = " ";
        double wide;
        double csi = Siz / 100.0;
//      uint chr = ccx[0].unicode();
        if (prefsManager->appPrefs.AvailFonts[ZFo].canRender(ccx[0]))
        {
                wide = prefsManager->appPrefs.AvailFonts[ZFo].charWidth(ccx[0])*(Siz / 10.0);
                QMatrix chma;
                chma.scale(csi, csi);
                uint gl = prefsManager->appPrefs.AvailFonts[ZFo].char2CMap(ccx[0]);
                FPointArray gly = prefsManager->appPrefs.AvailFonts[ZFo].glyphOutline(gl);
                if (gly.size() < 4)
                        return;
                gly.map(chma);
                chma = QMatrix();
                p->setFillMode(1);
                if (Reverse)
                {
                        chma.scale(-1, 1);
                        chma.translate(-wide, 0);
                        gly.map(chma);
                        chma = QMatrix();
                        chma.translate(xco, yco-(Siz / 10.0));
                }
                else
                        chma.translate(xco, yco-(Siz / 10.0));
                gly.map(chma);
                p->setupPolygon(&gly);
                p->setFillMode(1);
                if (mod > 1)
                        p->fillPath();
                if ((Style & 4) && ((mod % 2) != 0))
                {
                        p->setLineWidth(prefsManager->appPrefs.AvailFonts[ZFo].strokeWidth() * Siz / 20);
                        p->strokePath();
                }
                if (Style & 16)
                {
                        double st = prefsManager->appPrefs.AvailFonts[ZFo].strikeoutPos() * (Siz / 10.0);
                        p->setLineWidth(qMax(prefsManager->appPrefs.AvailFonts[ZFo].strokeWidth() * (Siz / 10.0), 1.0));
                        p->drawLine(FPoint(xco, yco-st), FPoint(xco+wide, yco-st));
                }
                if (Style & 8)
                {
                        double st = prefsManager->appPrefs.AvailFonts[ZFo].underlinePos() * (Siz / 10.0);
                        p->setLineWidth(qMax(prefsManager->appPrefs.AvailFonts[ZFo].strokeWidth() * (Siz / 10.0), 1.0));
                        p->drawLine(FPoint(xco, yco-st), FPoint(xco+wide, yco-st));
                }
        }
        else
        {
                p->setLineWidth(1);
                p->setPen(Qt::black);
                p->setFillMode(0);
                p->drawRect(xco, yco-Siz, (Siz / 10.0), (Siz / 10.0));
        }
}