Back to index

scribus-ng  1.3.4.dfsg+svn20071115
pageitem_pathtext.cpp
Go to the documentation of this file.
00001 /*
00002 For general Scribus (>=1.3.2) copyright and licensing information please refer
00003 to the COPYING file provided with the program. Following this notice may exist
00004 a copyright and/or license notice that predates the release of Scribus 1.3.2
00005 for which a new license (GPL+exception) is in place.
00006 */
00007 /***************************************************************************
00008                           pageitem.cpp  -  description
00009                              -------------------
00010     begin                : Sat Apr 7 2001
00011     copyright            : (C) 2001 by Franz Schmid
00012     email                : Franz.Schmid@altmuehlnet.de
00013  ***************************************************************************/
00014 
00015 /***************************************************************************
00016  *                                                                         *
00017  *   This program is free software; you can redistribute it and/or modify  *
00018  *   it under the terms of the GNU General Public License as published by  *
00019  *   the Free Software Foundation; either version 2 of the License, or     *
00020  *   (at your option) any later version.                                   *
00021  *                                                                         *
00022  ***************************************************************************/
00023 
00024 #include "pageitem_pathtext.h"
00025 #include "pageitem_pathtext.moc"
00026 #include <qpainter.h>
00027 #include <qpen.h>
00028 #include <qfont.h>
00029 #include <qregion.h>
00030 #include <qpoint.h>
00031 #include <qfileinfo.h>
00032 #include <qdrawutil.h>
00033 #include <qbitmap.h>
00034 #include <qpixmap.h>
00035 #include <qrect.h>
00036 #include <qregexp.h>
00037 #include <qmessagebox.h>
00038 #include <cmath>
00039 #include <cassert>
00040 
00041 #include "mpalette.h"
00042 #include "page.h"
00043 #include "pageitem.h"
00044 #include "prefsmanager.h"
00045 #include "scpaths.h"
00046 #include "scribus.h"
00047 #include "scribusstructs.h"
00048 #include "scribusdoc.h"
00049 #include "commonstrings.h"
00050 #include "undomanager.h"
00051 #include "undostate.h"
00052 #include "scconfig.h"
00053 
00054 #include "util.h"
00055 
00056 #include "text/nlsconfig.h"
00057 
00058 using namespace std;
00059 
00060 PageItem_PathText::PageItem_PathText(ScribusDoc *pa, double x, double y, double w, double h, double w2, QString fill, QString outline)
00061        : PageItem(pa, PageItem::PathText, x, y, w, h, w2, fill, outline)
00062 {
00063        firstChar = 0;
00064        MaxChars = itemText.length();
00065 }
00066 
00067 
00068 void PageItem_PathText::layout()
00069 {
00070        QPixmap pgPix(10, 10);
00071        QRect rd = QRect(0,0,9,9);
00072        ScPainter *painter = new ScPainter(&pgPix, pgPix.width(), pgPix.height());   
00073        DrawObj(painter, rd);
00074        painter->end();
00075        delete painter;
00076        Frame = true;
00077        updatePolyClip();
00078 }
00079 
00080 
00081 void PageItem_PathText::DrawObj_Item(ScPainter *p, QRect e, double sc)
00082 {
00083        itemText.invalidateAll();
00084        firstChar = 0;
00085        MaxChars = 0;
00086        int a;
00087        int chs;
00088        QString chstr, chstr2, chstr3;
00089        ScText *hl;
00090        double dx;
00091        double sp = 0;
00092        double oldSp = 0;
00093        double oCurX = 0;
00094        FPoint point = FPoint(0, 0);
00095        FPoint normal = FPoint(0, 0);
00096        FPoint tangent = FPoint(0, 0);
00097        FPoint extPoint = FPoint(0, 0);
00098        bool ext = false;
00099        bool first = true;
00100        double fsx = 0;
00101        uint seg = 0;
00102        double segLen = 0;
00103        double distCurX;
00104        QColor tmp;
00105        CurX = Extra;
00106        QString cachedStroke = "";
00107        QString cachedFill = "";
00108        int cachedFillShade = -1;
00109        int cachedStrokeShade = -1;
00110        QString actStroke = "";
00111        QString actFill = "";
00112        int actFillShade = -1;
00113        int actStrokeShade = -1;
00114        QColor cachedFillQ;
00115        QColor cachedStrokeQ;
00116        if (!m_Doc->layerOutline(LayerNr))
00117        {
00118               if (PoShow)
00119               {
00120                      if (lineColor() != CommonStrings::None && PoShow)
00121                      {
00122                             p->setupPolygon(&PoLine, false);
00123                             p->strokePath();
00124                      }
00125                      else
00126                      {
00127                             if (NamedLStyle.isEmpty())
00128                                    p->drawLine(FPoint(0, 0), FPoint(Width, 0));
00129                             else
00130                             {
00131                                    multiLine ml = m_Doc->MLineStyles[NamedLStyle];
00132                                    for (int it = ml.size()-1; it > -1; it--)
00133                                    {
00134                                           if ((ml[it].Color != CommonStrings::None) && (ml[it].Width != 0))
00135                                           {
00136                                                  SetFarbe(&tmp, ml[it].Color, ml[it].Shade);
00137                                                  p->setPen(tmp, ml[it].Width, static_cast<PenStyle>(ml[it].Dash), static_cast<PenCapStyle>(ml[it].LineEnd), static_cast<PenJoinStyle>(ml[it].LineJoin));
00138                                                  p->drawLine(FPoint(0, 0), FPoint(Width, 0));
00139                                           }
00140                                    }
00141                             }
00142                      }
00143               }
00144        }
00145        double totalTextLen = 0.0;
00146        double totalCurveLen = 0.0;
00147        double extraOffset = 0.0;
00148        if (itemText.length() != 0)
00149        {
00150               CurX += itemText.charStyle(0).fontSize() * itemText.charStyle(0).tracking() / 10000.0;
00151               totalTextLen += itemText.charStyle(0).fontSize() * itemText.charStyle(0).tracking() / 10000.0;
00152        }
00153        segLen = PoLine.lenPathSeg(seg);
00154        for (a = firstChar; a < itemText.length(); ++a)
00155        {
00156               hl = itemText.item(a);
00157               chstr = hl->ch;
00158               if (chstr[0] == SpecialChars::PAGENUMBER || chstr[0] == SpecialChars::PARSEP
00159                      || chstr[0] == SpecialChars::TAB || chstr == SpecialChars::LINEBREAK)
00160                      continue;
00161               if (a < itemText.length()-1)
00162                      chstr += itemText.text(a+1, 1);
00163               hl->glyph.yadvance = 0;
00164               layoutGlyphs(itemText.charStyle(a), chstr, hl->glyph);
00165               hl->glyph.shrink();
00166               if (hl->ch[0] == SpecialChars::OBJECT)
00167                      totalTextLen += (hl->embedded.getItem()->gWidth + hl->embedded.getItem()->lineWidth());
00168               else
00169                      totalTextLen += hl->glyph.wide()+hl->fontSize() * hl->tracking() / 10000.0;
00170        }
00171        for (uint segs = 0; segs < PoLine.size()-3; segs += 4)
00172        {
00173               totalCurveLen += PoLine.lenPathSeg(segs);
00174        }
00175        if ((itemText.defaultStyle().alignment() != 0) && (totalCurveLen >= totalTextLen + Extra))
00176        {
00177               if (itemText.defaultStyle().alignment() == 2)
00178               {
00179                      CurX = totalCurveLen  - totalTextLen;
00180                      CurX -= Extra;
00181               }
00182               if (itemText.defaultStyle().alignment() == 1)
00183                      CurX = (totalCurveLen - totalTextLen) / 2.0;
00184               if ((itemText.defaultStyle().alignment() == 3) || (itemText.defaultStyle().alignment() == 4))
00185                      extraOffset = (totalCurveLen - Extra  - totalTextLen) / static_cast<double>(itemText.length());
00186        }
00187 #ifndef NLS_PROTO
00188        for (a = firstChar; a < itemText.length(); ++a)
00189        {
00190               CurY = 0;
00191               hl = itemText.item(a);
00192               chstr = hl->ch;
00193               if (chstr[0] == SpecialChars::PAGENUMBER || chstr[0] == SpecialChars::PARSEP
00194                      || chstr[0] == SpecialChars::TAB || chstr == SpecialChars::LINEBREAK)
00195                      continue;
00196               chs = hl->fontSize();
00197               if (a < itemText.length()-1)
00198                      chstr += itemText.text(a+1, 1);
00199               hl->glyph.yadvance = 0;
00200               layoutGlyphs(itemText.charStyle(a), chstr, hl->glyph);
00201               hl->glyph.shrink();                                                           // HACK
00202               if (hl->ch[0] == SpecialChars::OBJECT)
00203                      dx = (hl->embedded.getItem()->gWidth + hl->embedded.getItem()->lineWidth()) / 2.0;
00204               else
00205                      dx = hl->glyph.wide() / 2.0;
00206 //            qDebug(QString("pathtext-draw: parent %1 parentc %2").arg((uint)itemText.paragraphStyle(a).parentStyle()).arg((uint)itemText.charStyle(a).parentStyle()));
00207 //            qDebug(QString("pathtext-draw: co %1 %2 %3 %4").arg(itemText.charStyle(a).fillColor()).arg(itemText.charStyle(a).fillShade()).arg(itemText.charStyle(a).strokeColor()).arg(itemText.charStyle(a).strokeShade()));
00208 //            qDebug(QString("pathtext-draw: fo %1 %2").arg(itemText.charStyle(a).font().scName()).arg(hl->glyph.glyph));
00209               CurX += dx;
00210               ext = false;
00211               while ( (seg < PoLine.size()-3) && (CurX > fsx + segLen))
00212               {
00213                      fsx += segLen;
00214                      seg += 4;
00215                      if (seg > PoLine.size()-3)
00216                             break;
00217                      segLen = PoLine.lenPathSeg(seg);
00218                      ext = true;
00219               }
00220               if (seg > PoLine.size()-3)
00221                      break;
00222               if (CurX > fsx + segLen)
00223                      break;
00224               if (ext)
00225               {
00226                      sp = 0;
00227                      distCurX = PoLine.lenPathDist(seg, 0, sp);
00228                      while (distCurX <= ((CurX - oCurX) - (fsx - oCurX)))
00229                      {
00230                             sp += 0.001;
00231                             distCurX = PoLine.lenPathDist(seg, 0, sp);
00232                      }
00233                      PoLine.pointTangentNormalAt(seg, sp, &point, &tangent, &normal );
00234                      CurX = (CurX - (CurX - fsx)) + distCurX;
00235                      oldSp = sp;
00236                      ext = false;
00237               }
00238               else
00239               {
00240                      if( seg < PoLine.size()-3 )
00241                      {
00242                             if (CurX > fsx + segLen)
00243                                    break;
00244                             distCurX = PoLine.lenPathDist(seg, oldSp, sp);
00245                             while (distCurX <= (CurX - oCurX))
00246                             {
00247                                    sp += 0.001;
00248                                    if (sp >= 1.0)
00249                                    {
00250                                           sp = 0.9999;
00251                                           break;
00252                                    }
00253                                    distCurX = PoLine.lenPathDist(seg, oldSp, sp);
00254                             }
00255                             PoLine.pointTangentNormalAt(seg, sp, &point, &tangent, &normal );
00256                             CurX = oCurX + distCurX;
00257                             oldSp = sp;
00258                      }
00259                      else
00260                             break;
00261               }
00262               hl->glyph.xoffset = 0;
00263               hl->glyph.yoffset = BaseOffs;
00264               hl->PtransX = tangent.x();
00265               hl->PtransY = tangent.y();
00266               hl->PRot = dx;
00267 //            qDebug(QString("'%1' (%2,%3) %4+%5").arg(itemText.text(a)).arg(point.x()).arg(point.y()).arg(CurX).arg(dx));
00268 #ifdef HAVE_CAIRO
00269               QWMatrix trafo = QWMatrix( 1, 0, 0, -1, -dx, 0 );
00270               if (textPathFlipped)
00271                      trafo *= QWMatrix(1, 0, 0, -1, 0, 0);
00272               if (textPathType == 0)
00273                      trafo *= QWMatrix( tangent.x(), tangent.y(), tangent.y(), -tangent.x(), point.x(), point.y() ); // ID's Rainbow mode
00274               else if (textPathType == 1)
00275                      trafo *= QWMatrix( 1, 0, 0, -1, point.x(), point.y() ); // ID's Stair Step mode
00276               else if (textPathType == 2)
00277               {
00278                      double a = 1;
00279                      if (tangent.x() < 0)
00280                             a = -1;
00281                      if (fabs(tangent.x()) > 0.1)
00282                             trafo *= QWMatrix( a, (tangent.y() / tangent.x()) * a, 0, -1, point.x(), point.y() ); // ID's Skew mode
00283                      else
00284                             trafo *= QWMatrix( a, 4 * a, 0, -1, point.x(), point.y() );
00285               }
00286 #else
00287               QWMatrix trafo = QWMatrix( 1, 0, 0, -1, -dx*sc, 0 );
00288               if (textPathFlipped)
00289                      trafo *= QWMatrix(1, 0, 0, -1, 0, 0);
00290               if (textPathType == 0)
00291                      trafo *= QWMatrix( tangent.x(), tangent.y(), tangent.y(), -tangent.x(), point.x()*sc, point.y()*sc ); // ID's Rainbow mode
00292               else if (textPathType == 1)
00293                      trafo *= QWMatrix( 1, 0, 0, -1, point.x()*sc, point.y()*sc ); // ID's Stair Step mode
00294               else if (textPathType == 2)
00295               {
00296                      double a = 1;
00297                      if (tangent.x() < 0)
00298                             a = -1;
00299                      if (fabs(tangent.x()) > 0.1)
00300                             trafo *= QWMatrix( a, (tangent.y() / tangent.x()) * a, 0, -1, point.x()*sc, point.y()*sc ); // ID's Skew mode
00301                      else
00302                             trafo *= QWMatrix( a, 4 * a, 0, -1, point.x()*sc, point.y()*sc );
00303               }
00304 #endif
00305               QWMatrix sca = p->worldMatrix();
00306               trafo *= sca;
00307               p->save();
00308               QWMatrix savWM = p->worldMatrix();
00309               p->setWorldMatrix(trafo);
00310               if (!m_Doc->RePos)
00311               {
00312                      actFill = itemText.charStyle(a).fillColor();
00313                      actFillShade = itemText.charStyle(a).fillShade();
00314                      if (actFill != CommonStrings::None)
00315                      {
00316                             if ((cachedFillShade != actFillShade) || (cachedFill != actFill))
00317                             {
00318                                    SetFarbe(&tmp, actFill, actFillShade);
00319                                    p->setBrush(tmp);
00320                                    cachedFillQ = tmp;
00321                                    cachedFill = actFill;
00322                                    cachedFillShade = actFillShade;
00323                             }
00324                             else
00325                                    p->setBrush(cachedFillQ);
00326                      }
00327                      actStroke = itemText.charStyle(a).strokeColor();
00328                      actStrokeShade = itemText.charStyle(a).strokeShade();
00329                      if (actStroke != CommonStrings::None)
00330                      {
00331                             if ((cachedStrokeShade != actStrokeShade) || (cachedStroke != actStroke))
00332                             {
00333                                    SetFarbe(&tmp, actStroke, actStrokeShade);
00334                                    p->setPen(tmp, 1, SolidLine, FlatCap, MiterJoin);
00335                                    cachedStrokeQ = tmp;
00336                                    cachedStroke = actStroke;
00337                                    cachedStrokeShade = actStrokeShade;
00338                             }
00339                             else
00340                                    p->setPen(cachedStrokeQ, 1, SolidLine, FlatCap, MiterJoin);
00341                      }
00342                      if (hl->ch[0] == SpecialChars::OBJECT)
00343                      {
00344                             p->translate(0.0, BaseOffs);
00345                             DrawObj_Embedded(p, e, itemText.charStyle(a), hl->embedded.getItem());
00346                      }
00347                      else
00348                             drawGlyphs(p, itemText.charStyle(a), hl->glyph);
00349               }
00350               hl->glyph.xoffset = point.x();
00351               hl->glyph.yoffset = point.y();
00352               p->setWorldMatrix(savWM);
00353               p->restore();
00354 #ifndef HAVE_CAIRO
00355               p->setZoomFactor(sc);
00356 #endif
00357               MaxChars = a+1;
00358               oCurX = CurX;
00359               CurX -= dx;
00360               if (hl->ch[0] == SpecialChars::OBJECT)
00361                      CurX += (hl->embedded.getItem()->gWidth + hl->embedded.getItem()->lineWidth());
00362               else
00363                      CurX += hl->glyph.wide()+hl->fontSize() * hl->tracking() / 10000.0 + extraOffset;
00364               first = false;
00365        }
00366        MaxChars++;  // ugly Hack
00367 #endif
00368 //     qDebug(QString("PageItem_PathText::DrawObj_Item repos=%1, %2 chars, [%3 %4 %5 %6 %7 %8] with %9").arg(m_Doc->RePos).arg(MaxChars)
00369 //               .arg(p->worldMatrix().m11()).arg(p->worldMatrix().m12()).arg(p->worldMatrix().m21()).arg(p->worldMatrix().m22()).arg(p->worldMatrix().dx()).arg(p->worldMatrix().dy())
00370 //               .arg(QString("pen %1 brush%2 device%3 isPainting=%4").arg(p->pen().rgb()).arg(p->brush().rgb()).arg(p->device()? p->device()->paintingActive() : -999))
00371 //               );
00372 }