Subversion Repositories Scribus

Rev

Rev 20307 | Rev 21146 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
4430 cbradney 1
/*
2
For general Scribus (>=1.3.2) copyright and licensing information please refer
3
to the COPYING file provided with the program. Following this notice may exist
4
a copyright and/or license notice that predates the release of Scribus 1.3.2
5
for which a new license (GPL+exception) is in place.
6
*/
3614 cbradney 7
/***************************************************************************
8
                          pageitem.cpp  -  description
9
                             -------------------
10
    begin                : Sat Apr 7 2001
11
    copyright            : (C) 2001 by Franz Schmid
12
    email                : Franz.Schmid@altmuehlnet.de
13
 ***************************************************************************/
14
 
15
/***************************************************************************
16
 *                                                                         *
17
 *   This program is free software; you can redistribute it and/or modify  *
18
 *   it under the terms of the GNU General Public License as published by  *
19
 *   the Free Software Foundation; either version 2 of the License, or     *
20
 *   (at your option) any later version.                                   *
21
 *                                                                         *
22
 ***************************************************************************/
23
 
24
#include "pageitem_pathtext.h"
10862 cbradney 25
#include <QGridLayout>
10220 cbradney 26
#include <QImage>
19080 craig 27
#include <QLabel>
10220 cbradney 28
#include <QList>
29
#include <QPainterPath>
30
 
3614 cbradney 31
#include <cassert>
32
 
16736 jghali 33
#include "scconfig.h"
34
 
35
#include "commonstrings.h"
3614 cbradney 36
#include "pageitem.h"
37
#include "prefsmanager.h"
16736 jghali 38
#include "scpage.h"
39
#include "scpainter.h"
3614 cbradney 40
#include "scpaths.h"
10601 mrdocs 41
#include "scraction.h"
19080 craig 42
 
3614 cbradney 43
#include "scribusstructs.h"
44
#include "scribusdoc.h"
45
#include "undomanager.h"
46
#include "undostate.h"
10601 mrdocs 47
#include "util.h"
10203 cbradney 48
#include "util_math.h"
21107 craig 49
#include "text/boxes.h"
50
#include "text/textlayoutpainter.h"
51
#include "text/screenpainter.h"
3614 cbradney 52
 
53
using namespace std;
54
 
55
PageItem_PathText::PageItem_PathText(ScribusDoc *pa, double x, double y, double w, double h, double w2, QString fill, QString outline)
17023 fschmid 56
        : PageItem(pa, PageItem::PathText, x, y, w, h, w2, fill, outline), itemRenderText(pa)
3614 cbradney 57
{
7939 fschmid 58
        firstChar = 0;
59
        MaxChars = itemText.length();
3614 cbradney 60
}
61
 
7994 avox 62
 
63
void PageItem_PathText::layout()
64
{
14408 fschmid 65
        QImage pgPix(10, 10, QImage::Format_ARGB32_Premultiplied);
11052 avox 66
        QRectF rd; // = QRect(0,0,9,9);
7994 avox 67
        ScPainter *painter = new ScPainter(&pgPix, pgPix.width(), pgPix.height());     
68
        DrawObj(painter, rd);
69
        painter->end();
70
        delete painter;
8108 fschmid 71
        updatePolyClip();
7994 avox 72
}
73
 
74
 
14681 fschmid 75
void PageItem_PathText::DrawObj_Item(ScPainter *p, QRectF cullingArea)
3614 cbradney 76
{
7964 avox 77
        itemText.invalidateAll();
7914 fschmid 78
        firstChar = 0;
8184 fschmid 79
        MaxChars = 0;
5753 jghali 80
        int a;
5721 avox 81
        QString chstr, chstr2, chstr3;
3614 cbradney 82
        double dx;
83
        FPoint point = FPoint(0, 0);
84
        FPoint tangent = FPoint(0, 0);
19831 craig 85
        CurX = m_textDistanceMargins.left();
21107 craig 86
 
13875 jghali 87
        if (!m_Doc->layerOutline(LayerID))
3614 cbradney 88
        {
6568 fschmid 89
                if (PoShow)
5572 fschmid 90
                {
12995 fschmid 91
                        p->setupPolygon(&PoLine, false);
92
                        if (NamedLStyle.isEmpty())
6568 fschmid 93
                        {
14168 fschmid 94
                                if ((!patternStrokeVal.isEmpty()) && (m_Doc->docPatterns.contains(patternStrokeVal)))
95
                                {
14398 fschmid 96
                                        if (patternStrokePath)
97
                                        {
98
                                                QPainterPath guidePath = PoLine.toQPainterPath(false);
14403 fschmid 99
                                                DrawStrokePattern(p, guidePath);
14398 fschmid 100
                                        }
101
                                        else
102
                                        {
103
                                                p->setPattern(&m_Doc->docPatterns[patternStrokeVal], patternStrokeScaleX, patternStrokeScaleY, patternStrokeOffsetX, patternStrokeOffsetY, patternStrokeRotation, patternStrokeSkewX, patternStrokeSkewY, patternStrokeMirrorX, patternStrokeMirrorY);
104
                                                p->setStrokeMode(ScPainter::Pattern);
105
                                                p->strokePath();
106
                                        }
14168 fschmid 107
                                }
14197 fschmid 108
                                else if (GrTypeStroke > 0)
109
                                {
110
                                        if ((!gradientStrokeVal.isEmpty()) && (!m_Doc->docGradients.contains(gradientStrokeVal)))
111
                                                gradientStrokeVal = "";
112
                                        if (!(gradientStrokeVal.isEmpty()) && (m_Doc->docGradients.contains(gradientStrokeVal)))
113
                                                stroke_gradient = m_Doc->docGradients[gradientStrokeVal];
114
                                        if (stroke_gradient.Stops() < 2) // fall back to solid stroking if there are not enough colorstops in the gradient.
115
                                        {
116
                                                if (lineColor() != CommonStrings::None)
117
                                                {
118
                                                        p->setBrush(strokeQColor);
119
                                                        p->setStrokeMode(ScPainter::Solid);
120
                                                }
121
                                                else
122
                                                        p->setStrokeMode(ScPainter::None);
123
                                        }
124
                                        else
125
                                        {
126
                                                p->setStrokeMode(ScPainter::Gradient);
127
                                                p->stroke_gradient = stroke_gradient;
128
                                                if (GrTypeStroke == 6)
14284 fschmid 129
                                                        p->setGradient(VGradient::linear, FPoint(GrStrokeStartX, GrStrokeStartY), FPoint(GrStrokeEndX, GrStrokeEndY), FPoint(GrStrokeStartX, GrStrokeStartY), GrStrokeScale, GrStrokeSkew);
14197 fschmid 130
                                                else
14284 fschmid 131
                                                        p->setGradient(VGradient::radial, FPoint(GrStrokeStartX, GrStrokeStartY), FPoint(GrStrokeEndX, GrStrokeEndY), FPoint(GrStrokeFocalX, GrStrokeFocalY), GrStrokeScale, GrStrokeSkew);
14197 fschmid 132
                                        }
14398 fschmid 133
                                        p->strokePath();
14197 fschmid 134
                                }
14168 fschmid 135
                                else if (lineColor() != CommonStrings::None)
14398 fschmid 136
                                {
14168 fschmid 137
                                        p->setStrokeMode(ScPainter::Solid);
14398 fschmid 138
                                        p->strokePath();
139
                                }
6568 fschmid 140
                        }
141
                        else
142
                        {
14168 fschmid 143
                                p->setStrokeMode(ScPainter::Solid);
12995 fschmid 144
                                multiLine ml = m_Doc->MLineStyles[NamedLStyle];
145
                                QColor tmp;
146
                                for (int it = ml.size()-1; it > -1; it--)
6568 fschmid 147
                                {
12995 fschmid 148
                                        if (ml[it].Color != CommonStrings::None) // && (ml[it].Width != 0))
6568 fschmid 149
                                        {
12995 fschmid 150
                                                SetQColor(&tmp, ml[it].Color, ml[it].Shade);
151
                                                p->setPen(tmp, ml[it].Width, static_cast<Qt::PenStyle>(ml[it].Dash), static_cast<Qt::PenCapStyle>(ml[it].LineEnd), static_cast<Qt::PenJoinStyle>(ml[it].LineJoin));
152
                                                p->strokePath();
6568 fschmid 153
                                        }
154
                                }
155
                        }
5572 fschmid 156
                }
3614 cbradney 157
        }
8114 fschmid 158
        double totalTextLen = 0.0;
159
        double totalCurveLen = 0.0;
160
        double extraOffset = 0.0;
5184 avox 161
        if (itemText.length() != 0)
8114 fschmid 162
        {
5691 avox 163
                CurX += itemText.charStyle(0).fontSize() * itemText.charStyle(0).tracking() / 10000.0;
8114 fschmid 164
                totalTextLen += itemText.charStyle(0).fontSize() * itemText.charStyle(0).tracking() / 10000.0;
165
        }
17231 fschmid 166
        itemRenderText.clear();
17408 fschmid 167
        itemRenderText.setDoc(m_Doc);
17023 fschmid 168
        itemRenderText.setDefaultStyle(itemText.defaultStyle());
8114 fschmid 169
        for (a = firstChar; a < itemText.length(); ++a)
170
        {
17205 fschmid 171
                CharStyle nstyle = itemText.charStyle(a);
172
                ParagraphStyle pstyle = itemText.paragraphStyle(a);
20307 jghali 173
                chstr = itemText.text(a, 1);
174
                if ((chstr[0] == SpecialChars::OBJECT) && (itemText.hasObject(a)))
17023 fschmid 175
                {
176
                        int pot = itemRenderText.length();
17407 fschmid 177
                        itemRenderText.insertObject(pot, itemText.object(a)->inlineCharID);
17023 fschmid 178
                }
17231 fschmid 179
                else
180
                {
181
                        if (!(chstr[0] == SpecialChars::PARSEP || chstr[0] == SpecialChars::TAB || chstr[0] == SpecialChars::LINEBREAK))
182
                                chstr = ExpandToken(a);
183
                        for (int cc = 0; cc < chstr.count(); cc++)
184
                        {
185
                                int pot = itemRenderText.length();
186
                                itemRenderText.insertChars(pot, chstr.mid(cc, 1));
187
                                itemRenderText.applyStyle(pot, pstyle);
188
                                itemRenderText.applyCharStyle(pot, 1, nstyle);
189
                        }
190
                }
17023 fschmid 191
                chstr.clear();
192
        }
18987 avox 193
        textLayout.setStory(&itemRenderText);
17260 fschmid 194
        int spaceCount = 0;
195
        double wordExtra = 0;
17023 fschmid 196
        for (a = firstChar; a < itemRenderText.length(); ++a)
197
        {
20307 jghali 198
                chstr = itemRenderText.text(a, 1);
11713 fschmid 199
                if (chstr[0] == SpecialChars::PAGENUMBER || chstr[0] == SpecialChars::PARSEP || chstr[0] == SpecialChars::PAGECOUNT
9919 jghali 200
                        || chstr[0] == SpecialChars::TAB || chstr[0] == SpecialChars::LINEBREAK)
8114 fschmid 201
                        continue;
17260 fschmid 202
                if (chstr[0] == SpecialChars::BLANK)
203
                        spaceCount++;
17023 fschmid 204
                if (a < itemRenderText.length()-1)
205
                        chstr += itemRenderText.text(a+1, 1);
21107 craig 206
                GlyphLayout glyphs = layoutGlyphs(itemRenderText.charStyle(a), chstr, itemRenderText.flags(a));
20307 jghali 207
                if (itemRenderText.hasObject(a))
21107 craig 208
                        totalTextLen += (itemRenderText.object(a)->width() + itemRenderText.object(a)->lineWidth()) * glyphs.scaleH;
8199 fschmid 209
                else
21107 craig 210
                        totalTextLen += glyphs.xadvance+itemRenderText.charStyle(a).fontSize() * itemRenderText.charStyle(a).tracking() / 10000.0;
8114 fschmid 211
        }
18114 jghali 212
        for (int segs = 0; segs < PoLine.size()-3; segs += 4)
8114 fschmid 213
        {
214
                totalCurveLen += PoLine.lenPathSeg(segs);
215
        }
19831 craig 216
        if ((itemRenderText.paragraphStyle(0).alignment() != 0) && (totalCurveLen >= totalTextLen + m_textDistanceMargins.left()))
8114 fschmid 217
        {
17205 fschmid 218
                if (itemRenderText.paragraphStyle(0).alignment() == 2)
8114 fschmid 219
                {
220
                        CurX = totalCurveLen  - totalTextLen;
19831 craig 221
                        CurX -= m_textDistanceMargins.left();
8114 fschmid 222
                }
17205 fschmid 223
                if (itemRenderText.paragraphStyle(0).alignment() == 1)
8114 fschmid 224
                        CurX = (totalCurveLen - totalTextLen) / 2.0;
17260 fschmid 225
                if (itemRenderText.paragraphStyle(0).alignment() == 3)
226
                {
227
                        if (spaceCount != 0)
228
                        {
229
                                extraOffset = 0;
19831 craig 230
                                wordExtra = (totalCurveLen - m_textDistanceMargins.left()  - totalTextLen) / static_cast<double>(spaceCount);
17260 fschmid 231
                        }
232
                        else
233
                        {
19831 craig 234
                                extraOffset = (totalCurveLen - m_textDistanceMargins.left()  - totalTextLen) / static_cast<double>(itemRenderText.length());
17260 fschmid 235
                                wordExtra = 0;
236
                        }
237
                }
238
                if (itemRenderText.paragraphStyle(0).alignment() == 4)
19831 craig 239
                        extraOffset = (totalCurveLen - m_textDistanceMargins.left() - totalTextLen) / static_cast<double>(itemRenderText.length());
8114 fschmid 240
        }
10138 fschmid 241
        QPainterPath guidePath = PoLine.toQPainterPath(false);
242
        QList<QPainterPath> pathList = decomposePath(guidePath);
243
        QPainterPath currPath = pathList[0];
244
        int currPathIndex = 0;
21107 craig 245
        PathLineBox* linebox = new PathLineBox();
17023 fschmid 246
        for (a = firstChar; a < itemRenderText.length(); ++a)
3614 cbradney 247
        {
248
                CurY = 0;
18987 avox 249
                PathData* pdata = & (textLayout.point(a));
20307 jghali 250
                chstr = itemRenderText.text(a,1);
11713 fschmid 251
                if (chstr[0] == SpecialChars::PAGENUMBER || chstr[0] == SpecialChars::PARSEP || chstr[0] == SpecialChars::PAGECOUNT
9919 jghali 252
                        || chstr[0] == SpecialChars::TAB || chstr[0] == SpecialChars::LINEBREAK)
3614 cbradney 253
                        continue;
17023 fschmid 254
                if (a < itemRenderText.length()-1)
255
                        chstr += itemRenderText.text(a+1, 1);
21107 craig 256
 
257
                GlyphLayout glyphs = layoutGlyphs(itemRenderText.charStyle(a), chstr, itemRenderText.flags(a));
258
                GlyphRun run(&itemRenderText.charStyle(a), itemRenderText.flags(a), a, a, itemRenderText.object(a));
259
                run.glyphs().append(glyphs);
260
 
20307 jghali 261
                if (itemRenderText.hasObject(a))
21107 craig 262
                        dx = (itemRenderText.object(a)->width() + itemRenderText.object(a)->lineWidth()) * glyphs.scaleH / 2.0;
8199 fschmid 263
                else
21107 craig 264
                        dx = glyphs.xadvance / 2.0;
3614 cbradney 265
                CurX += dx;
10138 fschmid 266
                double currPerc = currPath.percentAtLength(CurX);
267
                if (currPerc >= 0.9999999)
268
                {
269
                        currPathIndex++;
270
                        if (currPathIndex == pathList.count())
13536 jghali 271
                        {
272
                                MaxChars = a;
10138 fschmid 273
                                break;
13536 jghali 274
                        }
10138 fschmid 275
                        currPath = pathList[currPathIndex];
276
                        CurX = dx;
277
                        currPerc = currPath.percentAtLength(CurX);
278
                }
12060 fschmid 279
                double currAngle = currPath.angleAtPercent(currPerc);
280
                if (currAngle <= 180.0)
281
                        currAngle *= -1.0;
282
                else
283
                        currAngle = 360.0 - currAngle;
10138 fschmid 284
                QPointF currPoint = currPath.pointAtPercent(currPerc);
285
                tangent = FPoint(cos(currAngle * M_PI / 180.0), sin(currAngle * M_PI / 180.0));
286
                point = FPoint(currPoint.x(), currPoint.y());
21107 craig 287
                glyphs.xoffset = 0;
18987 avox 288
                pdata->PtransX = point.x();
289
                pdata->PtransY = point.y();
290
                pdata->PRot    = currAngle * M_PI / 180.0;
291
                pdata->PDx     = dx;
13951 fschmid 292
                QTransform trafo = QTransform( 1, 0, 0, -1, -dx, 0 );
7926 fschmid 293
                if (textPathFlipped)
13951 fschmid 294
                        trafo *= QTransform(1, 0, 0, -1, 0, 0);
7926 fschmid 295
                if (textPathType == 0)
13951 fschmid 296
                        trafo *= QTransform( tangent.x(), tangent.y(), tangent.y(), -tangent.x(), point.x(), point.y() ); // ID's Rainbow mode
7926 fschmid 297
                else if (textPathType == 1)
13951 fschmid 298
                        trafo *= QTransform( 1, 0, 0, -1, point.x(), point.y() ); // ID's Stair Step mode
7961 fschmid 299
                else if (textPathType == 2)
300
                {
301
                        double a = 1;
302
                        if (tangent.x() < 0)
303
                                a = -1;
304
                        if (fabs(tangent.x()) > 0.1)
13951 fschmid 305
                                trafo *= QTransform( a, (tangent.y() / tangent.x()) * a, 0, -1, point.x(), point.y() ); // ID's Skew mode
7961 fschmid 306
                        else
13951 fschmid 307
                                trafo *= QTransform( a, 4 * a, 0, -1, point.x(), point.y() );
7961 fschmid 308
                }
21107 craig 309
 
310
 
311
                const CharStyle& cStyle(run.style());
312
                double scaleV = cStyle.scaleV() / 1000.0;
313
                double offset = (cStyle.fontSize() / 10) * (cStyle.baselineOffset() / 1000.0);
314
                double ascent = cStyle.font().ascent(cStyle.fontSize()/10.00) * scaleV + offset;
315
                double descent = cStyle.font().descent(cStyle.fontSize()/10.00) * scaleV - offset;
316
                linebox->setAscent(ascent);
317
                linebox->setDescent(descent);
318
                Box* box;
319
                if (itemRenderText.hasObject(a))
7912 fschmid 320
                {
21107 craig 321
                        box = new ObjectBox(run);
322
                        box->setAscent(run.object()->height() - run.object()->lineWidth());
323
                        box->setDescent(0);
7912 fschmid 324
                }
21107 craig 325
                else
326
                {
327
                        box = new GlyphBox(run);
328
                        box->setAscent(linebox->ascent());
329
                        box->setDescent(linebox->descent());
330
                }
331
 
332
                box->setMatrix(trafo);
333
                linebox->addBox(box);
334
 
335
 
3614 cbradney 336
                MaxChars = a+1;
337
                CurX -= dx;
20307 jghali 338
                if (itemRenderText.hasObject(a))
21107 craig 339
                        CurX += (itemRenderText.object(a)->width() + itemRenderText.object(a)->lineWidth()) * glyphs.scaleH + extraOffset;
20307 jghali 340
                else if (chstr[0] == SpecialChars::BLANK)
21107 craig 341
                        CurX += glyphs.xadvance+itemRenderText.charStyle(a).fontSize() * itemRenderText.charStyle(a).tracking() / 10000.0 + wordExtra + extraOffset;
8183 fschmid 342
                else
21107 craig 343
                        CurX += glyphs.xadvance+itemRenderText.charStyle(a).fontSize() *itemRenderText.charStyle(a).tracking() / 10000.0 + extraOffset;
3614 cbradney 344
        }
21107 craig 345
 
346
        textLayout.addColumn(0, 0);
347
        textLayout.appendLine(linebox);
348
 
349
        if (!m_Doc->RePos)
350
        {
351
                int fm = p->fillMode();
352
                p->setFillMode(1);
353
                p->save();
354
                ScreenPainter painter(p, this);
355
                textLayout.render(&painter);
356
                p->setFillMode(fm);
357
                p->restore();
358
        }
3614 cbradney 359
}
10601 mrdocs 360
 
361
bool PageItem_PathText::createInfoGroup(QFrame *infoGroup, QGridLayout *infoGroupLayout)
362
{
363
        int Parag = 0;
364
        int Words = 0;
365
        int Chara = 0;
366
        int ParagN = 0;
367
        int WordsN = 0;
368
        int CharaN = 0;
369
 
370
        QLabel *infoCT = new QLabel(infoGroup);
371
        QLabel *linesCT = new QLabel(infoGroup);
372
        QLabel *linesT = new QLabel(infoGroup);
373
        QLabel *parCT = new QLabel(infoGroup);
374
        QLabel *parT = new QLabel(infoGroup);
375
        QLabel *wordCT = new QLabel(infoGroup);
376
        QLabel *wordT = new QLabel(infoGroup);
377
        QLabel *charCT = new QLabel(infoGroup);
378
        QLabel *charT = new QLabel(infoGroup);
379
 
380
 
381
        infoCT->setText("Text on a Path");
382
        infoGroupLayout->addWidget( infoCT, 0, 0, 1, 2, Qt::AlignCenter );
383
 
384
        WordAndPara(this, &Words, &Parag, &Chara, &WordsN, &ParagN, &CharaN);
385
        parCT->setText(tr("Paragraphs: "));
386
        infoGroupLayout->addWidget( parCT, 1, 0, Qt::AlignRight );
387
        if (ParagN != 0)
388
                parT->setText(QString::number(Parag+ParagN)+" ("+QString::number(ParagN)+")");
389
        else
390
                parT->setText(QString::number(Parag));
391
        infoGroupLayout->addWidget( parT, 1, 1 );
392
 
393
        linesCT->setText(tr("Lines: "));
394
        infoGroupLayout->addWidget( linesCT, 2, 0, Qt::AlignRight );
18987 avox 395
        linesT->setText(QString::number(textLayout.lines()));
10601 mrdocs 396
        infoGroupLayout->addWidget( linesT, 2, 1 );
397
 
398
 
399
        wordCT->setText(tr("Words: "));
400
        infoGroupLayout->addWidget( wordCT, 3, 0, Qt::AlignRight );
401
        if (WordsN != 0)
402
                wordT->setText(QString::number(Words+WordsN)+" ("+QString::number(WordsN)+")");
403
        else
404
                wordT->setText(QString::number(Words));
405
        infoGroupLayout->addWidget( wordT, 3, 1 );
406
 
407
        charCT->setText(tr("Chars: "));
408
        infoGroupLayout->addWidget(charCT, 4, 0, Qt::AlignRight );
409
        if (CharaN != 0)
410
                charT->setText(QString::number(Chara+CharaN)+" ("+QString::number(CharaN)+")");
411
        else
412
                charT->setText(QString::number(Chara));
413
        infoGroupLayout->addWidget( charT, 4, 1 );
414
        return true;
415
}
416
 
10934 cbradney 417
void PageItem_PathText::applicableActions(QStringList & actionList)
418
{
10940 cbradney 419
        actionList << "toolsEditWithStoryEditor";
420
        actionList << "itemConvertToOutlines";
10934 cbradney 421
}
10941 cbradney 422
 
423
QString PageItem_PathText::infoDescription()
424
{
425
        return QString();
426
}
18883 jghali 427
 
428
void PageItem_PathText::getVisualBoundingRect(double * x1, double * y1, double * x2, double * y2) const
429
{
430
        PageItem::getVisualBoundingRect(x1, y1, x2, y2);
431
        QRectF totalRect(QPointF(*x1, *y1), QPointF(*x2, *y2));
432
        QTransform clipTrans;
433
        clipTrans.translate(m_xPos, m_yPos);
434
        clipTrans.rotate(m_rotation);
435
        totalRect = totalRect.united(QRectF(clipTrans.mapRect(Clip.boundingRect())));
436
        totalRect.getCoords(x1, y1, x2, y2);
19080 craig 437
}