Subversion Repositories Scribus

Rev

Rev 14553 | Rev 14928 | 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
 
12269 cbradney 24
#include <QDebug>
9803 fschmid 25
#include <QList>
10220 cbradney 26
#include <QMatrix>
12269 cbradney 27
#include <QPalette>
10220 cbradney 28
#include <QPoint>
12269 cbradney 29
#include <QPolygon>
10220 cbradney 30
#include <QRegion>
12269 cbradney 31
#include <cassert>
3614 cbradney 32
#include <cmath>
33
 
12269 cbradney 34
 
10532 avox 35
#include "canvas.h"
10220 cbradney 36
#include "commonstrings.h"
37
#include "guidemanager.h"
3829 cbradney 38
#include "hyphenator.h"
3614 cbradney 39
#include "page.h"
40
#include "pageitem.h"
10220 cbradney 41
#include "pageitem_textframe.h"
3614 cbradney 42
#include "prefsmanager.h"
10220 cbradney 43
#include "scconfig.h"
10601 mrdocs 44
#include "scpainter.h"
3614 cbradney 45
#include "scpaths.h"
10601 mrdocs 46
#include "scraction.h"
3614 cbradney 47
#include "scribus.h"
10220 cbradney 48
#include "scribusdoc.h"
3614 cbradney 49
#include "scribusstructs.h"
4145 cbradney 50
#include "selection.h"
10220 cbradney 51
#include "text/nlsconfig.h"
3614 cbradney 52
#include "undomanager.h"
53
#include "undostate.h"
10601 mrdocs 54
#include "util.h"
10203 cbradney 55
#include "util_math.h"
12004 fschmid 56
#ifdef HAVE_CAIRO
57
        #include <cairo.h>
58
#endif
3614 cbradney 59
 
60
using namespace std;
61
 
62
PageItem_TextFrame::PageItem_TextFrame(ScribusDoc *pa, double x, double y, double w, double h, double w2, QString fill, QString outline)
63
        : PageItem(pa, PageItem::TextFrame, x, y, w, h, w2, fill, outline)
64
{
9816 avox 65
        invalid = true;
66
        firstChar = 0;
8931 cbradney 67
        cursorBiasBackward = false;
3829 cbradney 68
        unicodeTextEditMode = false;
69
        unicodeInputCount = 0;
70
        unicodeInputString = "";
13148 pierre 71
 
72
        connect(&itemText,SIGNAL(changed()), this, SLOT(slotInvalidateLayout()));
3614 cbradney 73
}
74
 
12839 fschmid 75
PageItem_TextFrame::PageItem_TextFrame(const PageItem & p) : PageItem(p)
76
{
77
        invalid = true;
78
        cursorBiasBackward = false;
79
        unicodeTextEditMode = false;
80
        unicodeInputCount = 0;
81
        unicodeInputString = "";
13148 pierre 82
 
83
        connect(&itemText,SIGNAL(changed()), this, SLOT(slotInvalidateLayout()));
12839 fschmid 84
}
5184 avox 85
 
10701 avox 86
static QRegion itemShape(PageItem* docItem, double xOffset, double yOffset)
5184 avox 87
{
88
        QRegion res;
9372 fschmid 89
        QMatrix pp;
90
//      pp.begin(view->viewport());
5184 avox 91
        pp.translate(docItem->xPos() - xOffset, docItem->yPos() - yOffset);
92
        pp.rotate(docItem->rotation());
93
        if (docItem->textFlowUsesBoundingBox())
94
        {
10284 fschmid 95
                QPolygon tcli(4);
5184 avox 96
                tcli.setPoint(0, QPoint(0,0));
97
                tcli.setPoint(1, QPoint(qRound(docItem->width()), 0));
98
                tcli.setPoint(2, QPoint(qRound(docItem->width()), qRound(docItem->height())));
99
                tcli.setPoint(3, QPoint(0, qRound(docItem->height())));
9372 fschmid 100
//              res = QRegion(pp.xForm(tcli));
101
                res = QRegion(pp.map(tcli));
5184 avox 102
        }
8445 fschmid 103
        else if ((docItem->textFlowUsesImageClipping()) && (docItem->imageClip.size() != 0))
5184 avox 104
        {
9803 fschmid 105
                QList<uint> Segs;
10284 fschmid 106
                QPolygon Clip2 = FlattenPath(docItem->imageClip, Segs);
9372 fschmid 107
//              res = QRegion(pp.xForm(Clip2));
9668 fschmid 108
                res = QRegion(pp.map(Clip2)).intersect(QRegion(pp.map(docItem->Clip)));
5184 avox 109
        }
8445 fschmid 110
        else if ((docItem->textFlowUsesContourLine()) && (docItem->ContourLine.size() != 0))
111
        {
9803 fschmid 112
                QList<uint> Segs;
10284 fschmid 113
                QPolygon Clip2 = FlattenPath(docItem->ContourLine, Segs);
9372 fschmid 114
//              res = QRegion(pp.xForm(Clip2));
115
                res = QRegion(pp.map(Clip2));
8445 fschmid 116
        }
117
        else
9372 fschmid 118
//              res = QRegion(pp.xForm(docItem->Clip));
119
                res = QRegion(pp.map(docItem->Clip));
120
//      pp.end();
5184 avox 121
        return  res;
122
}
123
 
124
QRegion PageItem_TextFrame::availableRegion(QRegion clip)
125
{
7181 cbradney 126
        QRegion result(clip);
5184 avox 127
        if (!isEmbedded)
128
        {
7181 cbradney 129
                int LayerLev = m_Doc->layerLevelFromNumber(LayerNr);
130
                uint docItemsCount=m_Doc->Items->count();
131
                Page* Mp=0;
132
                Page* Dp=0;
133
                PageItem* docItem=0;
134
                int LayerLevItem;
5184 avox 135
                if (!OnMasterPage.isEmpty())
136
                {
5559 avox 137
                        if ((savedOwnPage == -1) || (savedOwnPage >= signed(m_Doc->Pages->count())))
5375 fschmid 138
                                return result;
7175 fschmid 139
                        Mp = m_Doc->MasterPages.at(m_Doc->MasterNames[OnMasterPage]);
140
                        Dp = m_Doc->Pages->at(savedOwnPage);
11310 fschmid 141
                        int currentGroup = -1;
9856 fschmid 142
                        for (int a = 0; a < m_Doc->MasterItems.count(); ++a)
5184 avox 143
                        {
7175 fschmid 144
                                docItem = m_Doc->MasterItems.at(a);
145
                                LayerLevItem = m_Doc->layerLevelFromNumber(docItem->LayerNr);
10550 avox 146
                                if (((docItem->ItemNr > ItemNr) && (docItem->LayerNr == LayerNr)) || (LayerLevItem > LayerLev && m_Doc->layerFlow(docItem->LayerNr)))
5184 avox 147
                                {
11310 fschmid 148
                                        if (docItem->Groups.count() == 0)
149
                                                currentGroup = -1;
11444 fschmid 150
                                        if ((currentGroup != -1) && (docItem->Groups.count() != 0) && (currentGroup == docItem->Groups.top()))
11310 fschmid 151
                                                continue;
5620 jghali 152
                                        if (docItem->textFlowAroundObject())
5184 avox 153
                                        {
10701 avox 154
                                                result = result.subtract(itemShape(docItem, Mp->xOffset() - Dp->xOffset(), Mp->yOffset() - Dp->yOffset()));
5184 avox 155
                                        }
11310 fschmid 156
                                        if (docItem->isGroupControl)
157
                                                currentGroup = docItem->Groups.top();
5387 avox 158
                                }
159
                        } // for all masterItems
10240 jghali 160
                        // (JG) #6009 : disable possible interaction between master text frames and normal frames
161
                        // which have the text flow option set
162
                        /*if (!m_Doc->masterPageMode())
5184 avox 163
                        {
164
                                for (uint a = 0; a < docItemsCount; ++a)
165
                                {
7175 fschmid 166
                                        docItem = m_Doc->Items->at(a);
167
                                        Mp = m_Doc->MasterPages.at(m_Doc->MasterNames[OnMasterPage]);
168
                                        Dp = m_Doc->Pages->at(OwnPage);
5620 jghali 169
                                        if ((docItem->textFlowAroundObject()) && (docItem->OwnPage == OwnPage))
5184 avox 170
                                        {
171
                                                result = result.subtract(itemShape(docItem, m_Doc->view(), Mp->xOffset() - Dp->xOffset(), Mp->yOffset() - Dp->yOffset()));
172
                                        }
173
                                } // for all docItems
10240 jghali 174
                        } // if (! masterPageMode) */
5387 avox 175
                } // if (!OnMasterPage.isEmpty())
5184 avox 176
                else
177
                {
11310 fschmid 178
                        int currentGroup = -1;
5184 avox 179
                        for (uint a = 0; a < docItemsCount; ++a)
180
                        {
7175 fschmid 181
                                docItem = m_Doc->Items->at(a);
182
                                LayerLevItem = m_Doc->layerLevelFromNumber(docItem->LayerNr);
10550 avox 183
                                if (((docItem->ItemNr > ItemNr) && (docItem->LayerNr == LayerNr)) || (LayerLevItem > LayerLev && m_Doc->layerFlow(docItem->LayerNr)))
5184 avox 184
                                {
11310 fschmid 185
                                        if (docItem->Groups.count() == 0)
186
                                                currentGroup = -1;
11444 fschmid 187
                                        if ((currentGroup != -1) && (docItem->Groups.count() != 0) && (currentGroup == docItem->Groups.top()))
11310 fschmid 188
                                                continue;
189
                                        if (docItem->textFlowAroundObject())
10701 avox 190
                                                result = result.subtract(itemShape(docItem, 0, 0));
11310 fschmid 191
                                        if (docItem->isGroupControl)
192
                                                currentGroup = docItem->Groups.top();
5387 avox 193
                                }
194
                        } // for all docItems
11785 jghali 195
                } // if(OnMasterPage.isEmpty()          
5184 avox 196
        } // if(!Embedded)
197
        return result;
198
}
199
 
6144 avox 200
 
201
void PageItem_TextFrame::setShadow()
202
{
203
        if (OnMasterPage.isEmpty())
204
                return;
6366 avox 205
 
6144 avox 206
        QString newShadow = m_Doc->masterPageMode() ? OnMasterPage : QString::number(OwnPage);
207
        if (newShadow != currentShadow) {
6366 avox 208
                if (currentShadow == OnMasterPage) {
209
                        // masterpage was edited, clear all shadows
210
                        shadows.clear();
211
                }
6144 avox 212
                if (!shadows.contains(newShadow)) {
213
                        if (!shadows.contains(OnMasterPage)) {
214
                                shadows[OnMasterPage] = itemText;
7905 avox 215
//                              const ParagraphStyle& pstyle(shadows[OnMasterPage].paragraphStyle(0));
13085 jghali 216
//                              qDebug() << QString("Pageitem_Textframe: style of master: %1 align=%2").arg(pstyle.parent()).arg(pstyle.alignment());
217
//                              qDebug() << QString("Pageitem_Textframe: shadow itemText->%1").arg(OnMasterPage);
6144 avox 218
                        }
7887 avox 219
                        if (newShadow != OnMasterPage) {
220
                                shadows[newShadow] = shadows[OnMasterPage].copy();
221
//                              const ParagraphStyle& pstyle(shadows[newShadow].paragraphStyle(0));
13085 jghali 222
//                              qDebug() << QString("Pageitem_Textframe: style of shadow copy: %1 align=%2").arg(pstyle.parent()).arg(pstyle.alignment());
7887 avox 223
                        }
13085 jghali 224
//                      qDebug() << QString("Pageitem_Textframe: shadow %1<-%2").arg(newShadow).arg(OnMasterPage);
6144 avox 225
                }
226
                itemText = shadows[newShadow];
7887 avox 227
//              const ParagraphStyle& pstyle(itemText.paragraphStyle(0));
13085 jghali 228
//              qDebug() << QString("Pageitem_Textframe: style of shadow: %1 align=%2").arg(pstyle.parent()).arg(pstyle.alignment());
6144 avox 229
                invalid = true;
230
                currentShadow = newShadow;
231
        }
232
}
233
 
5291 avox 234
#ifdef NLS_PROTO
235
#include "text/pageitem_textframe.cpp"
236
#else
237
 
5778 avox 238
static void dumpIt(const ParagraphStyle& pstyle, QString indent = QString("->"))
239
{
10553 fschmid 240
        QString db = QString("%6%1/%2 @ %3: %4--%5 linespa%6: %7 align%8")
5778 avox 241
                   .arg(pstyle.name())
6733 avox 242
                   .arg(pstyle.parent())
5850 tsoots 243
                   .arg( (unsigned long int) &pstyle)
5778 avox 244
                   .arg(pstyle.leftMargin())
245
                   .arg(pstyle.rightMargin())
6805 avox 246
                   .arg(indent)
247
                   .arg(pstyle.lineSpacingMode())
248
                   .arg(pstyle.lineSpacing())
10553 fschmid 249
                   .arg(pstyle.alignment());
13085 jghali 250
        qDebug() << db;
5778 avox 251
        static QString more("  ");
6733 avox 252
        if (pstyle.hasParent())
253
                dumpIt(*dynamic_cast<const ParagraphStyle*>(pstyle.parentStyle()), more + indent);
5778 avox 254
}
255
 
5390 avox 256
 
8103 avox 257
static const bool legacy = true;
258
 
10553 fschmid 259
/*
7313 avox 260
static void layoutDropCap(GlyphLayout layout, double curX, double curY, double offsetX, double offsetY, double dropCapDrop)
261
{      
6370 avox 262
}
10553 fschmid 263
*/
6370 avox 264
 
8761 avox 265
/**
266
 Clones the tab fill char as often as necssary after all distances are known
267
 */
7905 avox 268
static void fillInTabLeaders(StoryText & itemText, LineSpec & curLine)
269
{
270
        // fill in tab leaders
271
        double xPos = curLine.x;
13178 jghali 272
        for (int ti= curLine.firstItem; ti <= curLine.lastItem; ++ti)
7905 avox 273
        {
274
                ScText * hl = itemText.item(ti);
9737 jghali 275
                if (hl->ch == SpecialChars::TAB)
7905 avox 276
                {
277
                        GlyphLayout * tglyph = hl->glyph.more;
278
 
279
                        if (!tglyph)
280
                                continue;
281
 
282
                        const CharStyle & charStyle(itemText.charStyle(ti));
283
                        double wt   = charStyle.font().glyphWidth(tglyph->glyph, charStyle.fontSize() * tglyph->scaleV / 10.0);
284
                        double len  = hl->glyph.xadvance;
285
                        int count   = static_cast<int>(len / wt);
286
                        double sPos = -len;
287
                        tglyph->xoffset = sPos;
13085 jghali 288
//                      qDebug() << QString("tab leaders: %1 %2 width=%3 count=%4").arg(sPos).arg(curLine.y).arg(wt).arg(count);
7905 avox 289
                        for (int cx = 1; cx < count; ++cx)
290
                        {
291
                                // clone fillchar
292
                                tglyph->grow();
293
                                *(tglyph->more) = *tglyph;
294
                                tglyph->more->more = NULL;
295
                                tglyph = tglyph->more;
296
                                tglyph->xoffset =  sPos + wt * cx;
297
                        }
298
                }
299
                xPos += hl->glyph.wide();
300
        }
301
}
302
 
303
 
7887 avox 304
 
7905 avox 305
enum TabStatus {
306
        TabNONE    = 0,
307
        TabLEFT    = TabNONE,
308
        TabRIGHT   = 1,
309
        TabPOINT   = 2,
310
        TabCOMMA   = 3,
311
        TabCENTER  = 4
7313 avox 312
};
6370 avox 313
 
8761 avox 314
 
315
/**
316
fields which describe what type of tab is currently active
317
 */
7313 avox 318
struct TabControl {
319
        bool   active;
7905 avox 320
        int    status;
7313 avox 321
        int    charIndex;
322
        double xPos;
7905 avox 323
        QChar  fillChar;
7313 avox 324
};
325
 
8761 avox 326
/**
327
fields which describe how the current line is placed into the frame
328
 */
7313 avox 329
struct LineControl {
330
        LineSpec line;
331
        int      itemsInLine;
332
        int      hyphenCount;
333
        double   colWidth;
8095 avox 334
        double   colGap;
7313 avox 335
        double   colLeft;
336
        double   colRight;
337
        int      column;
338
        bool     startOfCol;
339
        double   ascend;
340
        double   descend;
341
        double   width;
342
        double   xPos;
343
        double   yPos;
344
        int      breakIndex;
345
        double   breakXPos;
9047 avox 346
 
347
        double   maxShrink;
348
        double   maxStretch;
8095 avox 349
 
350
 
8761 avox 351
        /// remember frame dimensions and offsets
8095 avox 352
        void init(double w, double h, const MarginStruct& extra, double lCorr)
353
        {
354
                insets = extra;
355
                lineCorr = lCorr;
356
                frameWidth = w;
357
                frameHeight = h;
358
        }
359
 
8761 avox 360
        /// start at column 0
8095 avox 361
        void initColumns(double width, double gap)
362
        {
363
                column = 0;
364
                colWidth = width;
365
                colGap = gap;
366
        }
367
 
8761 avox 368
        /// move position to next column
8095 avox 369
        void nextColumn(double asce)
370
        {
371
                startOfCol = true;
372
                colLeft = (colWidth + colGap) * column + insets.Left + lineCorr;
373
                colRight = colLeft + colWidth;
8103 avox 374
                if (legacy)
375
                        colRight += insets.Right + lineCorr; //???
8095 avox 376
                xPos = colLeft;
377
                yPos = asce + insets.Top + lineCorr + 1;
378
        }
379
 
380
        bool isEndOfCol(double morespace = 0)
381
        {
382
                return yPos + morespace + insets.Bottom + lineCorr > frameHeight;
383
        }
384
 
8761 avox 385
        /**
386
                init fields for a new line at current position
387
         */
8095 avox 388
        void startLine(int first)
389
        {              
390
                itemsInLine = 0;
391
                line.x = xPos;
392
                line.y = yPos;
393
                line.firstItem = first;
394
                line.ascent = 10;
395
                line.descent = 0;
396
                line.width = 0;
397
                line.naturalWidth = 0;
13211 jghali 398
                line.colLeft = colLeft;
8095 avox 399
                breakIndex = -1;
400
                breakXPos = 0;
9047 avox 401
                maxShrink = 0;
402
                maxStretch = 0;
8095 avox 403
        }
404
 
9047 avox 405
 
406
        /// called when glyphs are placed on the line
407
        void rememberShrinkStretch(QChar ch, double wide, const ParagraphStyle& style)
408
        {
409
                if (SpecialChars::isExpandingSpace(ch))
410
                        maxShrink += (1 - style.minWordTracking()) * wide;
411
                else
412
                {
413
                        maxShrink += (1 - style.minGlyphExtension()) * wide;
414
                }
415
                maxStretch += (style.maxGlyphExtension() - 1) * wide;
12883 jghali 416
        }
9047 avox 417
 
8761 avox 418
        /// called when a possible break is passed
8095 avox 419
        void rememberBreak(int index, double pos)
420
        {
9047 avox 421
                if (pos > colRight)
422
                {
423
                        // only look for the first break behind the right edge
424
                        maxShrink = 0;
425
 
426
                        // check if we already have a better break
427
                        if (breakIndex >= 0)
428
                        {
429
                                double oldLooseness = qAbs(colRight - breakXPos);
430
 
431
                                double newLooseness = pos - colRight;
432
                                if (newLooseness >= oldLooseness)
433
                                        return;
434
                        }
435
                        breakXPos = colRight;
436
                }
437
                else
438
                {
439
                        breakXPos = pos;
440
                }
8095 avox 441
                breakIndex = index;
442
        }
443
 
8761 avox 444
        /// called when a mandatory break is found
8095 avox 445
        void breakLine(const StoryText& itemText, int last)
446
        {
447
                breakIndex = last;
448
                breakXPos  = line.x;
449
                for (int j = line.firstItem; j <= last; ++j)
450
                        if ( (itemText.item(j)->effects() & ScStyle_SuppressSpace) == 0)
451
                                breakXPos += itemText.item(j)->glyph.wide();
14553 jghali 452
                // #8194, #8717 : update line ascent and descent with sensible values
453
                // so that endOfLine() returns correct result
454
                updateHeightMetrics(itemText);
8095 avox 455
        }
456
 
8761 avox 457
        /// use the last remembered break to set line width and itemrange
8095 avox 458
        void finishLine(double endX)
459
        {
460
                line.lastItem = breakIndex;
461
                line.naturalWidth = breakXPos - line.x;
462
                line.width = endX - line.x;
9047 avox 463
                maxShrink = maxStretch = 0;
8095 avox 464
        }
465
 
466
 
467
        bool isEndOfLine(double moreSpace = 0)
468
        {
8103 avox 469
                if (legacy)
9047 avox 470
                        return xPos + insets.Right + lineCorr + moreSpace - maxShrink >= colRight;
8103 avox 471
                else
9047 avox 472
                        return xPos + moreSpace - maxShrink >= colRight;
8095 avox 473
        }
474
 
8761 avox 475
        /// find x position to start current line
9372 fschmid 476
        double startOfLine(const QRegion& shape, const QMatrix& pf2, double ascent, double descent, double morespace)
8095 avox 477
        {
478
                QPoint pt1, pt2;
479
                double tmpX = xPos;
480
                pt1 = QPoint(static_cast<int>(ceil(tmpX)), static_cast<int>(yPos + descent));
481
                pt2 = QPoint(static_cast<int>(ceil(tmpX)), static_cast<int>(ceil(yPos - ascent)));
482
                // increase pt1/pt2 until i-beam reaches end of line
9372 fschmid 483
                while ((!shape.contains(pf2.map(pt1))) || (!shape.contains(pf2.map(pt2))))
8095 avox 484
                {
485
                        tmpX++;
9047 avox 486
                        if (xPos + (legacy? lineCorr + insets.Right : 0) + lineCorr + morespace >= colRight)
8095 avox 487
                        {
488
                                return tmpX;
489
                        }
490
                        pt1 = QPoint(static_cast<int>(ceil(tmpX)), static_cast<int>(yPos + descent));
491
                        pt2 = QPoint(static_cast<int>(ceil(tmpX)), static_cast<int>(ceil(yPos - ascent)));
492
                }
493
                return tmpX;
494
        }
495
 
8761 avox 496
        /// find x position where this line must end
14533 jghali 497
        double endOfLine(const QRegion& shape, const QMatrix& pf2, double morespace = 0)
8095 avox 498
        {
13402 jghali 499
                // Keep old code for reference
500
                /*double EndX = floor(qMax(line.x, qMin(colRight,breakXPos) - 1));
8095 avox 501
                QPoint pt1, pt2;
13085 jghali 502
                //      qDebug() << QString("endx start=%1, hl is '%2'").arg(EndX).arg(hl->ch);
8095 avox 503
                do {
504
                        EndX += 0.125;
8103 avox 505
                        pt1 = QPoint(qRound(ceil(EndX + insets.Right)), static_cast<int>(yPos+descent));
506
                        pt2 = QPoint(qRound(ceil(EndX + insets.Right)), static_cast<int>(ceil(yPos-ascent)));
13402 jghali 507
                } while ( (EndX + (legacy? lineCorr + insets.Right : 0) < colRight - morespace)
508
                        && shape.contains(pf2.map(pt1))
509
                        && shape.contains(pf2.map(pt2))
510
                        );*/
511
 
512
                // if we aren't restricted further, we'll end at this maxX:
513
                double maxX = colRight - morespace;
514
                if (legacy) maxX -= (lineCorr + insets.Right);
515
 
516
                double StartX = floor(qMax(line.x, qMin(colRight,breakXPos) - 1));
517
                int xPos  = static_cast<int>(ceil(maxX + insets.Right));
14533 jghali 518
                int yDesc = static_cast<int>(yPos+line.descent);
519
                int yAsc  = static_cast<int>(ceil(yPos-line.ascent));
13402 jghali 520
 
521
                QPoint pt12 (xPos, yDesc);
522
                QPoint pt22 (xPos, yAsc);
523
 
524
                // simple and fast case: transformed line completely falls within range
525
                // this will happen if we don't wrap around anything - ie. very often
526
                QPolygon p;
527
                p.append (pf2.map (QPoint (StartX, yAsc)));
528
                p.append (pf2.map (QPoint (StartX, yDesc)));
529
                p.append (pf2.map (pt12));
530
                p.append (pf2.map (pt22));
531
                // check if something gets in the way
532
                QRegion lineI = shape.intersected (p.boundingRect());
533
                // if the intersection only has 1 rectangle, then nothing gets in the way
534
                if (lineI.numRects() == 1)
535
                {
536
                        int xPos = qRound(ceil(StartX + 0.125 + insets.Right));
537
                        pt12.setX(xPos);
538
                        pt22.setX(xPos);
539
                        if (shape.contains(pf2.map(pt12)) && shape.contains(pf2.map(pt22)))
540
                        {
541
                                QRect rect = lineI.rects().at(0);
542
                                double  mx = qMax(rect.left(), rect.right()) - pf2.dx();
543
                                int steps = static_cast<int>((mx - StartX - insets.Right - 2)/0.125);
544
                                if (steps > 0)
545
                                        StartX += steps * 0.125;
546
                        }
547
                }
548
 
549
                // qDebug()<<"endOfLine: going for the hard case";
550
                double EndX2 = StartX;
551
                double Interval = 0.125;
552
                do {
553
                        EndX2 += Interval;
554
                        int xPos = qRound(ceil(EndX2 + insets.Right));
555
                        pt12.setX (xPos);
556
                        pt22.setX (xPos);
557
                } while ((EndX2 < maxX) && shape.contains(pf2.map(pt12)) && shape.contains(pf2.map(pt22)));
558
 
559
                /*if (EndX!=EndX2)
560
                {
561
                        qDebug()<<EndX<<EndX2<<StartX<<maxX;
562
                        qDebug()<<"DIFFERING ENDX!!!!!";
563
                }*/
564
                return EndX2;
8095 avox 565
        }
566
 
567
 
8956 avox 568
        double getLineAscent(const StoryText& itemText)
569
        {
570
                double result = 0;
571
                if ((itemText.text(line.firstItem) == SpecialChars::PARSEP) || (itemText.text(line.firstItem) == SpecialChars::LINEBREAK))
572
                        result = itemText.charStyle(line.firstItem).font().ascent(itemText.charStyle(line.firstItem).fontSize() / 10.0);
573
                else if (itemText.object(line.firstItem) != 0)
10394 cbradney 574
                        result = qMax(result, (itemText.object(line.firstItem)->gHeight + itemText.object(line.firstItem)->lineWidth()) * (itemText.charStyle(line.firstItem).scaleV() / 1000.0));
8956 avox 575
                else //if (itemText.charStyle(current.line.firstItem).effects() & ScStyle_DropCap == 0)
576
                        result = itemText.charStyle(line.firstItem).font().realCharAscent(itemText.text(line.firstItem), itemText.charStyle(line.firstItem).fontSize() / 10.0);
577
                for (int zc = 0; zc < itemsInLine; ++zc)
578
                {
579
                        QChar ch = itemText.text(line.firstItem + zc);
11713 fschmid 580
                        if ((ch == SpecialChars::PAGENUMBER) || (ch == SpecialChars::PAGECOUNT))
8956 avox 581
                                ch = '8'; // should have highest ascender even in oldstyle
582
                        const CharStyle& cStyle(itemText.charStyle(line.firstItem + zc));
583
                        if ((ch == SpecialChars::TAB) || (ch == QChar(10))
584
                                || (ch == SpecialChars::PARSEP) || (ch == SpecialChars::NBHYPHEN)
585
                                || (ch == SpecialChars::COLBREAK) || (ch == SpecialChars::LINEBREAK)
586
                                || (ch == SpecialChars::FRAMEBREAK) || (ch.isSpace()))
587
                                continue;
588
                        double asce;
589
                        if (itemText.object(line.firstItem + zc) != 0)
590
                                asce = itemText.object(line.firstItem + zc)->gHeight + itemText.object(line.firstItem + zc)->lineWidth() * (cStyle.scaleV() / 1000.0);
591
                        else //if (itemText.charStyle(current.line.firstItem + zc).effects() & ScStyle_DropCap == 0)
592
                                asce = cStyle.font().realCharAscent(ch, cStyle.fontSize() / 10.0);
13085 jghali 593
                        //      qDebug() << QString("checking char 'x%2' with ascender %1 > %3").arg(asce).arg(ch.unicode()).arg(result);
10394 cbradney 594
                        result = qMax(result, asce);
8956 avox 595
                }
596
                return result;
597
        }
14553 jghali 598
 
599
        double getLineDescent(const StoryText& itemText)
600
        {
601
                double result = 0;
602
                if ((itemText.text(line.firstItem) == SpecialChars::PARSEP) || (itemText.text(line.firstItem) == SpecialChars::LINEBREAK))
603
                        result = itemText.charStyle(line.firstItem).font().descent(itemText.charStyle(line.firstItem).fontSize() / 10.0);
604
                else if (itemText.object(line.firstItem) != 0)
605
                        result = 0.0;
606
                else //if (itemText.charStyle(current.line.firstItem).effects() & ScStyle_DropCap == 0)
607
                        result = itemText.charStyle(line.firstItem).font().realCharDescent(itemText.text(line.firstItem), itemText.charStyle(line.firstItem).fontSize() / 10.0);
608
                for (int zc = 0; zc < itemsInLine; ++zc)
609
                {
610
                        QChar ch = itemText.text(line.firstItem + zc);
611
                        if ((ch == SpecialChars::PAGENUMBER) || (ch == SpecialChars::PAGECOUNT))
612
                                ch = '8'; // should have highest ascender even in oldstyle
613
                        const CharStyle& cStyle(itemText.charStyle(line.firstItem + zc));
614
                        if ((ch == SpecialChars::TAB) || (ch == QChar(10))
615
                                || (ch == SpecialChars::PARSEP) || (ch == SpecialChars::NBHYPHEN)
616
                                || (ch == SpecialChars::COLBREAK) || (ch == SpecialChars::LINEBREAK)
617
                                || (ch == SpecialChars::FRAMEBREAK) || (ch.isSpace()))
618
                                continue;
619
                        double desc;
620
                        if (itemText.object(line.firstItem + zc) != 0)
621
                                desc = 0.0;
622
                        else //if (itemText.charStyle(current.line.firstItem + zc).effects() & ScStyle_DropCap == 0)
623
                                desc = cStyle.font().realCharDescent(ch, cStyle.fontSize() / 10.0);
624
                        //      qDebug() << QString("checking char 'x%2' with ascender %1 > %3").arg(asce).arg(ch.unicode()).arg(result);
625
                        result = qMax(result, desc);
626
                }
627
                return result;
628
        }
8956 avox 629
 
630
        double getLineHeight(const StoryText& itemText)
631
        {
632
                double result = 0;
633
                if (itemText.object(line.firstItem) != 0)
10394 cbradney 634
                        result = qMax(result, (itemText.object(line.firstItem)->gHeight + itemText.object(line.firstItem)->lineWidth()) * (itemText.charStyle(line.firstItem).scaleV() / 1000.0));
8956 avox 635
                else //if (itemText.charStyle(current.line.firstItem).effects() & ScStyle_DropCap == 0)
636
                        result = itemText.charStyle(line.firstItem).font().height(itemText.charStyle(line.firstItem).fontSize() / 10.0);
637
                for (int zc = 0; zc < itemsInLine; ++zc)
638
                {
639
                        QChar ch = itemText.text(line.firstItem+zc);
640
                        if ((ch == SpecialChars::TAB) || (ch == QChar(10))
641
                                || (ch == SpecialChars::PARSEP) || (ch == SpecialChars::NBHYPHEN)
642
                                || (ch == SpecialChars::COLBREAK) || (ch == SpecialChars::FRAMEBREAK)
643
                                || (ch == SpecialChars::LINEBREAK) || (ch.isSpace()))
644
                                continue;
645
                        double asce;
646
                        if (itemText.object(line.firstItem+zc) != 0)
647
                                asce = (itemText.object(line.firstItem+zc)->gHeight + itemText.object(line.firstItem+zc)->lineWidth()) * (itemText.charStyle(line.firstItem+zc).scaleV() / 1000.0);
648
                        else //if (itemText.charStyle(current.line.firstItem+zc).effects() & ScStyle_DropCap == 0)
649
                                asce = itemText.charStyle(line.firstItem+zc).font().height(itemText.charStyle(line.firstItem+zc).fontSize() / 10.0);
13085 jghali 650
                        //      qDebug() << QString("checking char 'x%2' with ascender %1 > %3").arg(asce).arg(ch.unicode()).arg(result);
10394 cbradney 651
                        result = qMax(result, asce);
8956 avox 652
                }
653
                return result;
654
        }
14553 jghali 655
 
656
        void updateHeightMetrics(const StoryText& itemText)
657
        {
658
                double asce, desc;
659
                line.ascent  = 0;
660
                line.descent = 0;
661
                for (int zc = 0; zc < itemsInLine; ++zc)
662
                {
663
                        QChar ch = itemText.text(line.firstItem+zc);
664
                        if ((ch == SpecialChars::TAB) || (ch == QChar(10))
665
                                || (ch == SpecialChars::PARSEP) || (ch == SpecialChars::NBHYPHEN)
666
                                || (ch == SpecialChars::COLBREAK) || (ch == SpecialChars::FRAMEBREAK)
667
                                || (ch == SpecialChars::LINEBREAK) || (ch.isSpace()))
668
                                continue;
669
                        const CharStyle& cStyle(itemText.charStyle(line.firstItem + zc));
670
                        if (itemText.object(line.firstItem+zc) != 0)
671
                        {
672
                                asce = (itemText.object(line.firstItem+zc)->gHeight + itemText.object(line.firstItem+zc)->lineWidth()) * (itemText.charStyle(line.firstItem+zc).scaleV() / 1000.0);
673
                                desc = 0.0;
674
                        }
675
                        else //if (itemText.charStyle(current.line.firstItem+zc).effects() & ScStyle_DropCap == 0)
676
                        {
677
                                asce = cStyle.font().realCharAscent(ch, cStyle.fontSize() / 10.0);
678
                                desc = cStyle.font().realCharDescent(ch, cStyle.fontSize() / 10.0);
679
                        }
680
                        //      qDebug() << QString("checking char 'x%2' with ascender %1 > %3").arg(asce).arg(ch.unicode()).arg(result);
681
                        line.ascent  = qMax(line.ascent, asce);
682
                        line.descent = qMax(line.descent, desc);
683
                }
684
        }
8956 avox 685
 
686
 
8095 avox 687
private:
688
        double frameWidth;
689
        double frameHeight;
690
        MarginStruct insets;
691
        double lineCorr;
7313 avox 692
};
693
 
694
 
8095 avox 695
 
8761 avox 696
/// called when line length is known and line is to be justified
8095 avox 697
static void justifyLine(StoryText& itemText, LineSpec& line)
698
{
8761 avox 699
 
9047 avox 700
        double glyphNatural = 0;
701
        double spaceNatural = 0;
702
        double glyphExtension;
703
        double spaceExtension;
704
 
705
        const ParagraphStyle& style(itemText.paragraphStyle(line.firstItem));
706
 
707
        // measure natural widths for glyphs and spaces
9054 avox 708
        for (int sof = line.firstItem; sof <= line.lastItem; ++sof)
8095 avox 709
        {
9047 avox 710
                if (!SpecialChars::isExpandingSpace(itemText.text(sof)))
711
                {
712
                        glyphNatural += itemText.item(sof)->glyph.wide();
713
                }
714
                else if ( (itemText.item(sof)->effects() & ScStyle_SuppressSpace) == 0)
715
                {
716
                        spaceNatural += itemText.item(sof)->glyph.wide();
717
                }
8095 avox 718
        }
9047 avox 719
 
720
        // decision: prio 1: stretch glyph;  prio 2: stretch spaces
721
 
722
        if (line.width < spaceNatural + glyphNatural * style.minGlyphExtension() && spaceNatural > 0)
723
        {
724
                glyphExtension = style.minGlyphExtension() - 1;
725
                spaceExtension = (line.width - glyphNatural * (1+glyphExtension) ) / spaceNatural  - 1;
726
        }
727
        else if (line.width < spaceNatural + glyphNatural * style.maxGlyphExtension() && glyphNatural > 0)
728
        {
729
                spaceExtension = 0;
730
                glyphExtension = (line.width - spaceNatural) / glyphNatural  - 1;
731
        }
8095 avox 732
        else
9047 avox 733
        {
734
                glyphExtension = style.maxGlyphExtension() - 1;
735
                if (spaceNatural > 0)
736
                        spaceExtension = (line.width - glyphNatural * (1+glyphExtension) ) / spaceNatural  - 1;
737
                else
738
                        spaceExtension = 0;
739
        }
8095 avox 740
 
9047 avox 741
        double glyphScale = 1 + glyphExtension;
742
 
743
/*
13085 jghali 744
        qDebug() << QString("justify: line = %7 natural = %1 + %2 = %3 (%4); spaces + %5%%; min=%8; glyphs + %6%%; min=%9")
9047 avox 745
                   .arg(spaceNatural).arg(glyphNatural).arg(spaceNatural+glyphNatural).arg(line.naturalWidth)
746
                   .arg(spaceExtension).arg(glyphExtension).arg(line.width)
13085 jghali 747
                   .arg(style.minWordTracking()).arg(style.minGlyphExtension());
9047 avox 748
        */
749
 
750
        // distribute whitespace on spaces and glyphs
751
        for (int yof = line.firstItem; yof <= line.lastItem; ++yof)
8095 avox 752
        {
9047 avox 753
                double wide = itemText.item(yof)->glyph.wide();
754
                if (!SpecialChars::isExpandingSpace(itemText.text(yof)))
8095 avox 755
                {
9047 avox 756
                        itemText.item(yof)->glyph.last()->xadvance += wide * glyphExtension;
757
                        GlyphLayout* glyph = &(itemText.item(yof)->glyph);
758
                        while (glyph)
759
                        {
760
                                glyph->xoffset *= glyphScale;
761
                                glyph->scaleH *= glyphScale;
762
                                glyph = glyph->more;
763
                        }
8095 avox 764
                }
9047 avox 765
                else if ((itemText.item(yof)->effects() & ScStyle_SuppressSpace) == 0)
766
                {
767
                        itemText.item(yof)->glyph.last()->xadvance += wide * spaceExtension;
768
                }
8095 avox 769
        }
770
}
771
 
772
 
9047 avox 773
/// called when linelength is known and line is not justified
774
static void indentLine(StoryText& itemText, LineSpec& line, double leftIndent)
8095 avox 775
{
9047 avox 776
        if (line.naturalWidth > line.width)
777
        {
778
                justifyLine(itemText, line);
779
        }
780
        if (leftIndent > 0)
781
        {
782
                line.x += leftIndent;
783
                line.width -= leftIndent;
784
        }
8095 avox 785
}
786
 
8761 avox 787
/// calculate how much the first char should stick out to the left
8095 avox 788
static double opticalLeftMargin(const StoryText& itemText, const LineSpec& line)
789
{
790
        int b = line.firstItem;
791
        while (b < line.lastItem && (itemText.item(b)->effects() & ScStyle_SuppressSpace))
792
                   ++b;
793
 
794
        double chs = itemText.charStyle(b).fontSize() * (itemText.charStyle(b).scaleH() / 1000.0);
795
        QChar chr = itemText.text(b);
796
        double leftCorr = itemText.charStyle(b).font().realCharWidth(chr, chs / 10.0);
10517 cbradney 797
        if (QString("'´`").indexOf(chr) >= 0
8761 avox 798
                || chr == QChar(0x2018) // quote 6
799
                || chr == QChar(0x2019) // quote 9
800
                || chr == QChar(0x201a) // lower quote 9
801
                || chr == QChar(0x201b) // upper reversed 9 6
802
                || chr == QChar(0x2039) // single guillemet <
803
                || chr == QChar(0x203a) // single guillemet >
8095 avox 804
                )
805
                leftCorr *= -0.7;
10517 cbradney 806
        else if (QString("\"").indexOf(chr) >= 0
8761 avox 807
                         || chr == QChar(0x00ab) // guillemet <<
808
                         || chr == QChar(0x00bb) // guillemet >>
809
                         || chr == QChar(0x201c) // quote 66
810
                         || chr == QChar(0x201d) // quote 99
811
                         || chr == QChar(0x201e) // lower quote 99
812
                         || chr == QChar(0x201f) // upper reversed 99
8095 avox 813
                         )
814
                leftCorr *= -0.5;
815
        else {
816
                leftCorr = itemText.charStyle(b).font().charWidth(QChar(' '), chs / 10.0, chr);
817
                leftCorr -= itemText.charStyle(b).font().charWidth(QChar(' '), chs / 10.0);
818
//                              double leftCorr2 = itemText.charStyle(a).font().charWidth(QChar('K'), chs / 10.0, chr);
819
//                              leftCorr2 -= itemText.charStyle(a).font().charWidth(QChar('K'), chs / 10.0);
8562 jghali 820
//                              leftCorr = qMin(leftCorr, leftCorr2);
8095 avox 821
        }
822
        return leftCorr;
823
}
824
 
825
 
8761 avox 826
 
827
/// calculate how much the last char should stick out to the right
8095 avox 828
static double opticalRightMargin(const StoryText& itemText, const LineSpec& line)
829
{
830
        int b = line.lastItem;
831
        while (b > line.firstItem &&
8177 avox 832
                   (SpecialChars::isBreakingSpace(itemText.text(b)) || SpecialChars::isBreak(itemText.text(b)))
8095 avox 833
                   )
834
                --b;
835
        if (b >= line.firstItem)
836
        {
837
                double chs = itemText.charStyle(b).fontSize() * (itemText.charStyle(b).scaleH() / 1000.0);
838
                QChar chr = (itemText.item(b)->effects() & ScStyle_SmartHyphenVisible) ?
839
                        QChar('-') : itemText.text(b);
840
                double rightCorr = itemText.charStyle(b).font().realCharWidth(chr, chs / 10.0);
10517 cbradney 841
                if (QString("-,.`´'~").indexOf(chr) >= 0
8095 avox 842
                        || chr == QChar(0x2018)
843
                        || chr == QChar(0x2019)
844
                        || chr == QChar(0x201a)
845
                        || chr == QChar(0x201b)
846
                        || chr == QChar(0x2039)
847
                        || chr == QChar(0x203a)
8761 avox 848
                        || chr == QChar(0x2032) // PRIME
8095 avox 849
                        )
850
                        rightCorr *= 0.7;
10517 cbradney 851
                else if (QString(";:\"").indexOf(chr) >= 0
8095 avox 852
                                 || chr == QChar(0x00ab)
853
                                 || chr == QChar(0x00bb)
854
                                 || chr == QChar(0x201c)
855
                                 || chr == QChar(0x201d)
856
                                 || chr == QChar(0x201e)
857
                                 || chr == QChar(0x201f)
8761 avox 858
                                 || chr == QChar(0x2013) // EN DASH
859
                                 || chr == QChar(0x2033) // double prime
8095 avox 860
                                 )
861
                        rightCorr *= 0.5;
862
                else {
863
                        rightCorr = itemText.charStyle(b).font().charWidth(chr, chs / 10.0);
864
                        rightCorr -= itemText.charStyle(b).font().charWidth(chr, chs / 10.0, QChar('.'));
865
                }
866
                return rightCorr;
867
        }
868
        return 0.0;
869
}
870
 
871
 
8761 avox 872
 
873
 
874
 
5362 avox 875
void PageItem_TextFrame::layout()
3614 cbradney 876
{
13045 jghali 877
//      qDebug()<<"==Layout==" << itemName() ;
13034 pierre 878
//      printBacktrace(24);
5732 avox 879
        if (BackBox != NULL && BackBox->invalid) {
880
//              qDebug("textframe: len=%d, going back", itemText.length());
7379 avox 881
                invalid = false;
8060 avox 882
                PageItem_TextFrame* prevInChain = dynamic_cast<PageItem_TextFrame*>(BackBox);
883
                if (!prevInChain)
13085 jghali 884
                        qDebug() << QString("layout(): backBox=%1 is no textframe!!").arg((ulong)BackBox);
8060 avox 885
                else
886
                        BackBox->layout();
5362 avox 887
                return;
888
        }
6370 avox 889
        else if (!invalid && OnMasterPage.isEmpty()) {
13085 jghali 890
//              qDebug() << QString("textframe: len=%1, invalid=%2 OnMasterPage=%3: no relayout").arg(itemText.length()).arg(invalid).arg(OnMasterPage);
5732 avox 891
                return;
892
        }
8334 avox 893
        if (invalid && BackBox == NULL)
894
                firstChar = 0;
895
 
13085 jghali 896
//      qDebug() << QString("textframe(%1,%2): len=%3, start relayout at %4").arg(Xpos).arg(Ypos).arg(itemText.length()).arg(firstInFrame());
9380 fschmid 897
//      ScribusView* view = m_Doc->view();
9372 fschmid 898
        QMatrix pf2;
5362 avox 899
        QPoint pt1, pt2;
11776 jghali 900
        /*QRegion cm;*/
7969 avox 901
        double chs, chsd = 0;
8095 avox 902
        double oldCurY, EndX, OFs, wide, kernVal;
7313 avox 903
        QString chstr;
5362 avox 904
        ScText *hl;
6805 avox 905
        ParagraphStyle style;
8095 avox 906
        int /*ParagraphStyle::OpticalMarginType*/ opticalMargins = ParagraphStyle::OM_None;
5362 avox 907
 
908
        bool outs = false;
909
        bool fBorder = false;
910
        bool goNoRoom = false;
911
        bool goNextColumn = false;
7905 avox 912
 
913
        TabControl tabs;
914
        tabs.active    = false;     // RTab
915
        tabs.status    = TabNONE;   // TabCode
916
        tabs.charIndex = -1;        // StartRT
917
        tabs.xPos      = 0;         // RTabX
918
 
9803 fschmid 919
        QList<ParagraphStyle::TabRecord> tTabValues;
7905 avox 920
        tTabValues.clear();
921
 
5362 avox 922
        bool DropCmode = false;
923
        bool AbsHasDrop = false;
7969 avox 924
        double desc=0, asce=0, maxDY=0, desc2=0, maxDX=0;
6370 avox 925
        double DropCapDrop = 0;
11776 jghali 926
        int    DropLines = 0;
927
        int    DropLinesCount = 0;
5362 avox 928
 
11776 jghali 929
 
6144 avox 930
        itemText.clearLines();
8095 avox 931
 
932
        double lineCorr = 0;
933
        if (lineColor() != CommonStrings::None)
934
                lineCorr = m_lineWidth / 2.0;
935
 
936
        // TODO: refactor this into PageItem
937
        MarginStruct extra;
938
        extra.Top = TExtra;
939
        extra.Left = Extra;
940
        extra.Right = RExtra;
941
        extra.Bottom = BExtra;
942
 
943
        LineControl current;
944
        current.init(Width, Height, extra, lineCorr);
945
        current.initColumns(columnWidth(), ColGap);
946
        current.hyphenCount = 0;
947
 
5778 avox 948
        // dump styles
949
/*     
950
        for (int i=0; i < itemText.nrOfParagraphs(); ++i) {
951
                const ParagraphStyle& pstyle(itemText.paragraphStyle(itemText.endOfParagraph(i)));
13085 jghali 952
                qDebug("par %d:", i);
5778 avox 953
                dumpIt(pstyle);
954
        }
13085 jghali 955
        qDebug() << "default:";
5778 avox 956
        dumpIt(itemText.defaultStyle());
6805 avox 957
*/     
5778 avox 958
 
9372 fschmid 959
//      pf2.begin(view->viewport());
5362 avox 960
        pf2.translate(Xpos, Ypos);
961
        pf2.rotate(Rot);
6144 avox 962
 
963
        setShadow();
5732 avox 964
        if ((itemText.length() != 0)) // || (NextBox != 0))
8095 avox 965
        {
5408 avox 966
                // determine layout area
9372 fschmid 967
                QRegion cl = availableRegion(QRegion(pf2.map(Clip)));
14383 jghali 968
                if (cl.isEmpty())
969
                {
970
                        MaxChars = firstInFrame();
971
                        goto NoRoom;
972
                }
5362 avox 973
 
974
                if (imageFlippedH())
975
                {
976
                        pf2.translate(Width, 0);
977
                        pf2.scale(-1, 1);
978
                }
979
                if (imageFlippedV())
980
                {
981
                        pf2.translate(0, Height);
982
                        pf2.scale(1, -1);
983
                }
5408 avox 984
 
8095 avox 985
                current.nextColumn(0);
986
 
5559 avox 987
                // find start of first line
7887 avox 988
                if (firstInFrame() < itemText.length())
5362 avox 989
                {
7887 avox 990
                        hl = itemText.item(firstInFrame());
991
                        style = itemText.paragraphStyle(firstInFrame());
8956 avox 992
                        if (style.lineSpacingMode() == ParagraphStyle::AutomaticLineSpacing)
993
                        {
994
                                style.setLineSpacing(style.charStyle().font().height(style.charStyle().fontSize() / 10.0));
13085 jghali 995
//                              qDebug() << QString("auto linespacing: %1").arg(style.lineSpacing());
8956 avox 996
                        }
11768 jghali 997
                        else if (style.lineSpacingMode() == ParagraphStyle::BaselineGridLineSpacing)
998
                                style.setLineSpacing(m_Doc->typographicSettings.valueBaseGrid);
8956 avox 999
 
13085 jghali 1000
//                      qDebug() << QString("style @0: %1 -- %2, %4/%5 char: %3").arg(style.leftMargin()).arg(style.rightMargin())
1001
//                                 .arg(style.charStyle().asString()).arg(style.name()).arg(style.parent()?style.parent()->name():"");
6805 avox 1002
                        if (style.hasDropCap())
3614 cbradney 1003
                        {
8062 avox 1004
                                if (style.lineSpacingMode() == ParagraphStyle::BaselineGridLineSpacing)
6805 avox 1005
                                        chs = qRound(m_Doc->typographicSettings.valueBaseGrid  * style.dropCapLines() * 10);
5362 avox 1006
                                else
6805 avox 1007
                                        chs = qRound(style.lineSpacing() * style.dropCapLines() * 10);
3614 cbradney 1008
                        }
6370 avox 1009
                        else
5691 avox 1010
                                chs = hl->fontSize();
5980 avox 1011
                        desc2 = -hl->font().descent(chs / 10.0);
8095 avox 1012
                        current.yPos = extra.Top + lineCorr;
13085 jghali 1013
//                      qDebug() << QString("first line at y=%1").arg(current.yPos);
5362 avox 1014
                }
6370 avox 1015
                else // empty itemText:
5362 avox 1016
                {
6370 avox 1017
                        desc2 = -itemText.defaultStyle().charStyle().font().descent(itemText.defaultStyle().charStyle().fontSize() / 10.0);
8095 avox 1018
                        current.yPos = itemText.defaultStyle().lineSpacing() + extra.Top+lineCorr-desc2;
5362 avox 1019
                }
8095 avox 1020
                current.startLine(firstInFrame());
5362 avox 1021
                outs = false;
1022
                OFs = 0;
1023
                MaxChars = 0;
5721 avox 1024
                for (int a = firstInFrame(); a < itemText.length(); ++a)
5362 avox 1025
                {
5721 avox 1026
                        hl = itemText.item(a);
8060 avox 1027
                        if (a > 0 && itemText.text(a-1) == SpecialChars::PARSEP)
1028
                                style = itemText.paragraphStyle(a);
8095 avox 1029
                        if (current.itemsInLine == 0)
8060 avox 1030
                                opticalMargins = style.opticalMargins();
1031
 
13085 jghali 1032
//                      qDebug() << QString("style pos %1: %2 (%3)").arg(a).arg(style.alignment()).arg(style.parent());
12782 jghali 1033
                        const CharStyle& charStyle =  (hl->ch != SpecialChars::PARSEP? itemText.charStyle(a) : itemText.paragraphStyle(a).charStyle());
8060 avox 1034
                        if (!charStyle.parent().isEmpty())
1035
                        {
13085 jghali 1036
//                              qDebug() << QString("charstyle pos %1: %2 (%3 %4 %5 %6 %7 %8 %9)").arg(a).arg(charStyle.parent())
8060 avox 1037
//                                         .arg((uint)charStyle.parentStyle()).arg(charStyle.font().scName()).arg(charStyle.fontSize())
13085 jghali 1038
//                                         .arg(charStyle.fillColor()).arg(charStyle.strokeColor()).arg(charStyle.parentStyle()->name()).arg((uint)charStyle.parentStyle()->parentStyle());
8060 avox 1039
                        }                              
13085 jghali 1040
//                      qDebug() << QString("charstyle pos %1: %2 (%3)").arg(a).arg(charStyle.asString()).arg(charStyle.fontSize());
1041
//                      qDebug() << QString("style @%6: %1 -- %2, %4/%5 char: %3").arg(style.leftMargin()).arg(style.rightMargin())
7287 avox 1042
//                                 .arg(style.charStyle().asString()).arg(style.name()).arg(style.parent())
13085 jghali 1043
//                                 .arg(a);
5721 avox 1044
 
6144 avox 1045
                        chstr = ExpandToken(a);
13085 jghali 1046
//                      qDebug() << QString("expanded token: '%1'").arg(chstr);
6144 avox 1047
                        if (chstr.isEmpty())
8861 cbradney 1048
                                chstr = SpecialChars::ZWNBSPACE;
8956 avox 1049
                        if (style.lineSpacingMode() == ParagraphStyle::AutomaticLineSpacing)
1050
                        {
1051
                                style.setLineSpacing(style.charStyle().font().height(style.charStyle().fontSize() / 10.0));
1052
                        }
11768 jghali 1053
                        else if (style.lineSpacingMode() == ParagraphStyle::BaselineGridLineSpacing)
1054
                                style.setLineSpacing(m_Doc->typographicSettings.valueBaseGrid);
5408 avox 1055
                        // find out about par gap and dropcap
5721 avox 1056
                        if (a == firstInFrame())
3614 cbradney 1057
                        {
8814 cbradney 1058
                                if (a == 0 || itemText.text(a-1) == SpecialChars::PARSEP)
5362 avox 1059
                                {
8814 cbradney 1060
                                        current.yPos += style.gapBefore();
7313 avox 1061
                                        if (chstr[0] != SpecialChars::PARSEP)
5362 avox 1062
                                        {
5721 avox 1063
                                                DropCmode = style.hasDropCap();
5362 avox 1064
                                                if (DropCmode)
5721 avox 1065
                                                        DropLines = style.dropCapLines();
5362 avox 1066
                                        }
1067
                                        else
1068
                                                DropCmode = false;
1069
                                }
3614 cbradney 1070
                        }
8814 cbradney 1071
 
6370 avox 1072
                        {  // local block for 'fl'
5691 avox 1073
                                StyleFlag fl = hl->effects();
1074
                                fl &= ~ScStyle_DropCap;
1075
                                fl &= ~ScStyle_SmartHyphenVisible;
1076
                                hl->setEffects(fl);
1077
                        }
8814 cbradney 1078
 
8150 avox 1079
                        // No space at begin of line, 
1080
                        if (legacy)
3614 cbradney 1081
                        {
8150 avox 1082
                                // unless at begin of par (eeks)
9737 jghali 1083
                                if ( (current.itemsInLine == 0) && (SpecialChars::isBreakingSpace(hl->ch))
8177 avox 1084
                                         && (a > 0 && ! SpecialChars::isBreak(itemText.text(a-1)))
1085
                                         && ! (a > 0 && SpecialChars::isBreakingSpace(itemText.text(a-1))
8150 avox 1086
                                                   && (itemText.charStyle(a-1).effects() & ScStyle_SuppressSpace) != ScStyle_SuppressSpace))
1087
                                {
1088
                                        hl->setEffects(hl->effects() | ScStyle_SuppressSpace);
1089
                                        hl->glyph.xadvance = 0;
1090
                                        continue;
1091
                                }
1092
                                else
1093
                                        hl->setEffects(hl->effects() & ~ScStyle_SuppressSpace);
5362 avox 1094
                        }
8150 avox 1095
                        else // from 134 on use NBSPACE for this effect
1096
                        {
12477 jghali 1097
                                if ( current.itemsInLine == 0 && (SpecialChars::isBreakingSpace(hl->ch) || hl->ch.isSpace()))
8150 avox 1098
                                {
1099
                                        hl->setEffects(hl->effects() | ScStyle_SuppressSpace);
1100
                                        hl->glyph.xadvance = 0;
1101
                                        continue;
1102
                                }
1103
                                else
1104
                                        hl->setEffects(hl->effects() & ~ScStyle_SuppressSpace);
1105
                        }
13085 jghali 1106
                        //      qDebug() << QString("textframe(%1,%2): len=%3, fontsize=%4, ascent=%5").arg(Xpos).arg(Ypos).arg(itemText.length())
1107
//                                                      .arg(charStyle.fontSize()).arg(charStyle.font().ascent());                              
8095 avox 1108
                        if (current.itemsInLine == 0)
5362 avox 1109
                        {
5732 avox 1110
                                // more about par gap and dropcaps
10550 avox 1111
                                if ((a > firstInFrame() && itemText.text(a-1) == SpecialChars::PARSEP) || (a == 0 && BackBox == 0 && !current.startOfCol)) // after || always evaluates to false? FIXME
3614 cbradney 1112
                                {
13085 jghali 1113
//                                      qDebug() << QString("gap before2: y=%1+%2").arg(current.yPos).arg(style.gapBefore());
8095 avox 1114
                                        current.yPos += style.gapBefore();
6370 avox 1115
                                        DropCapDrop = 0;
7313 avox 1116
                                        if (chstr[0] != SpecialChars::PARSEP)
5721 avox 1117
                                                DropCmode = style.hasDropCap();
5362 avox 1118
                                        else
1119
                                                DropCmode = false;
1120
                                        if (DropCmode)
1121
                                        {
5721 avox 1122
                                                DropLines = style.dropCapLines();
8062 avox 1123
                                                if (style.lineSpacingMode() == ParagraphStyle::BaselineGridLineSpacing)
6370 avox 1124
                                                        DropCapDrop = m_Doc->typographicSettings.valueBaseGrid * (DropLines-1);
5362 avox 1125
                                                else
1126
                                                {
5721 avox 1127
                                                        if (style.lineSpacingMode() == ParagraphStyle::FixedLineSpacing)
6805 avox 1128
                                                                DropCapDrop = style.lineSpacing() * (DropLines-1);
5362 avox 1129
                                                        else
6370 avox 1130
                                                                DropCapDrop = charStyle.font().height(style.charStyle().fontSize() / 10.0) * (DropLines-1);
5362 avox 1131
                                                }
13085 jghali 1132
//                                              qDebug() << QString("dropcapdrop: y=%1+%2").arg(current.yPos).arg(DropCapDrop);
8095 avox 1133
                                                current.yPos += DropCapDrop;
5362 avox 1134
                                        }
3614 cbradney 1135
                                }
5362 avox 1136
                        }
5408 avox 1137
                        // find charsize & y pos
5362 avox 1138
                        if (DropCmode)
1139
                        {
5408 avox 1140
                                // dropcap active?
8062 avox 1141
                                if (style.lineSpacingMode() == ParagraphStyle::BaselineGridLineSpacing)
6370 avox 1142
                                        DropCapDrop = m_Doc->typographicSettings.valueBaseGrid * (DropLines-1);
1143
                                else
3614 cbradney 1144
                                {
6370 avox 1145
                                        if (style.lineSpacingMode() == ParagraphStyle::FixedLineSpacing)
6805 avox 1146
                                                DropCapDrop = style.lineSpacing() * (DropLines-1);
6370 avox 1147
                                        else
1148
                                                DropCapDrop = charStyle.font().height(style.charStyle().fontSize() / 10.0) * (DropLines-1);
1149
                                }
1150
 
11767 jghali 1151
                                // FIXME : we should ensure that fonts are loaded before calls to layout()
1152
                                // ScFace::realCharHeight()/Ascent() ensure font is loaded thanks to an indirect call to char2CMap()
1153
                                // ScFace::ascent() can be called safely afterwards
1154
                                double realCharHeight = charStyle.font().realCharHeight(chstr[0], 1);
1155
                                double realCharAscent = charStyle.font().realCharAscent(chstr[0], 1);
1156
                                double fontAscent     = charStyle.font().ascent(style.charStyle().fontSize() / 10.0);
8062 avox 1157
                                if (style.lineSpacingMode() == ParagraphStyle::BaselineGridLineSpacing)
6370 avox 1158
                                {
11767 jghali 1159
                                        chsd = (10 * ((m_Doc->typographicSettings.valueBaseGrid * (DropLines-1) + fontAscent) / realCharHeight));
1160
                                        chs  = (10 * ((m_Doc->typographicSettings.valueBaseGrid * (DropLines-1) + fontAscent) / realCharAscent));
3614 cbradney 1161
                                }
5362 avox 1162
                                else
3614 cbradney 1163
                                {
5721 avox 1164
                                        if (style.lineSpacingMode() == ParagraphStyle::FixedLineSpacing)
5362 avox 1165
                                        {
11767 jghali 1166
                                                chsd = (10 * ((style.lineSpacing() * (DropLines-1) + fontAscent) / realCharHeight));
1167
                                                chs  = (10 * ((style.lineSpacing() * (DropLines-1) + fontAscent) / realCharAscent));
5184 avox 1168
                                        }
3614 cbradney 1169
                                        else
1170
                                        {
6144 avox 1171
                                                double currasce = charStyle.font().height(style.charStyle().fontSize() / 10.0);
11767 jghali 1172
                                                chsd = (10 * ((currasce * (DropLines-1) + fontAscent) / realCharHeight));
1173
                                                chs  = (10 * ((currasce * (DropLines-1) + fontAscent) / realCharAscent));
3614 cbradney 1174
                                        }
5362 avox 1175
                                }
5691 avox 1176
                                hl->setEffects(hl->effects() | ScStyle_DropCap);
6370 avox 1177
                                hl->glyph.yoffset -= DropCapDrop;
5362 avox 1178
                        }
5408 avox 1179
                        else // ! dropCapMode
5362 avox 1180
                        {
9737 jghali 1181
                                if ((hl->ch == SpecialChars::OBJECT) && (hl->embedded.hasItem()))
8177 avox 1182
                                        chs = qRound((hl->embedded.getItem()->gHeight + hl->embedded.getItem()->lineWidth()) * 10);
5362 avox 1183
                                else
6144 avox 1184
                                        chs = charStyle.fontSize();
5362 avox 1185
                        }
8098 avox 1186
                        // find tracking
1187
                        if (current.itemsInLine == 0)
1188
                        {
1189
                                itemText.item(a)->setEffects(itemText.item(a)->effects() | ScStyle_StartOfLine);
1190
                                kernVal = 0;
1191
                        }
1192
                        else
1193
                        {
1194
                                kernVal = 0; // chs * charStyle.tracking() / 10000.0;
1195
                                itemText.item(a)->setEffects(itemText.item(a)->effects() & ~ScStyle_StartOfLine);
1196
                        }
6144 avox 1197
                        hl->glyph.yadvance = 0;
5980 avox 1198
                        oldCurY = layoutGlyphs(*hl, chstr, hl->glyph);
5408 avox 1199
                        // find out width of char
9737 jghali 1200
                        if ((hl->ch == SpecialChars::OBJECT) && (hl->embedded.hasItem()))
14418 jghali 1201
                        {
8177 avox 1202
                                wide = hl->embedded.getItem()->gWidth + hl->embedded.getItem()->lineWidth();
14425 jghali 1203
                                hl->glyph.xadvance = wide * hl->glyph.scaleH;
14418 jghali 1204
                        }
5362 avox 1205
                        else
1206
                        {
6354 avox 1207
                                wide = hl->glyph.wide();
8814 cbradney 1208
                                // apply kerning
6354 avox 1209
                                if (a+1 < itemText.length())
1210
                                {
1211
                                        uint glyph2 = charStyle.font().char2CMap(itemText.text(a+1));
7356 avox 1212
                                        double kern= charStyle.font().glyphKerning(hl->glyph.glyph, glyph2, chs / 10.0) * hl->glyph.scaleH;
1213
                                        wide += kern;
1214
                                        hl->glyph.xadvance += kern;
6354 avox 1215
                                }
5362 avox 1216
                        }
1217
                        if (DropCmode)
1218
                        {
5408 avox 1219
                                // drop caps are wider...
9737 jghali 1220
                                if ((hl->ch == SpecialChars::OBJECT) && (hl->embedded.hasItem()))
5362 avox 1221
                                {
8177 avox 1222
                                        wide = hl->embedded.getItem()->gWidth + hl->embedded.getItem()->lineWidth();
8062 avox 1223
                                        if (style.lineSpacingMode() == ParagraphStyle::BaselineGridLineSpacing)
5362 avox 1224
                                                asce = m_Doc->typographicSettings.valueBaseGrid * DropLines;
1225
                                        else
3614 cbradney 1226
                                        {
5721 avox 1227
                                                if (style.lineSpacingMode() == ParagraphStyle::FixedLineSpacing)
6805 avox 1228
                                                        asce = style.lineSpacing() * DropLines;
5362 avox 1229
                                                else
6144 avox 1230
                                                        asce = charStyle.font().height(style.charStyle().fontSize() / 10.0) * DropLines;
3614 cbradney 1231
                                        }
6144 avox 1232
                                        hl->glyph.scaleH /= hl->glyph.scaleV;
8177 avox 1233
                                        hl->glyph.scaleV = (asce / (hl->embedded.getItem()->gHeight + hl->embedded.getItem()->lineWidth()));
6144 avox 1234
                                        hl->glyph.scaleH *= hl->glyph.scaleV;
5362 avox 1235
                                }
1236
                                else
1237
                                {
7313 avox 1238
                                        wide = charStyle.font().realCharWidth(chstr[0], chsd / 10.0);
1239
                                        asce = charStyle.font().realCharHeight(chstr[0], chsd / 10.0);
13085 jghali 1240
//                                      qDebug() QString("dropcaps pre: chsd=%1 realCharHeight = %2 chstr=%3").arg(chsd).arg(asce).arg(chstr2[0]);
6144 avox 1241
                                        hl->glyph.scaleH /= hl->glyph.scaleV;
8072 avox 1242
                                        hl->glyph.scaleV = (asce / charStyle.font().realCharHeight(chstr[0], charStyle.fontSize() / 10.0));
6144 avox 1243
                                        hl->glyph.scaleH *= hl->glyph.scaleV;
5362 avox 1244
                                }
6370 avox 1245
                                hl->glyph.xadvance = wide;
5362 avox 1246
                                desc2 = 0;
1247
                                desc = 0;
1248
                        }
8814 cbradney 1249
                        else // !DropCMode
5362 avox 1250
                        {
13085 jghali 1251
//                              qDebug( ) << QString("textframe ascent/descent: fontsize=%1, ascent=%2, descent=%3")
1252
//                                         .arg(charStyle.fontSize()).arg(charStyle.font().ascent()).arg(charStyle.font().descent());                           
8761 avox 1253
 
9737 jghali 1254
                                if (SpecialChars::isExpandingSpace(hl->ch))
8900 cbradney 1255
                                {
8931 cbradney 1256
                                        double wordtracking = charStyle.wordTracking();
8900 cbradney 1257
                                        hl->glyph.xadvance *= wordtracking;
1258
                                        wide *= wordtracking;
1259
                                }
8761 avox 1260
 
5408 avox 1261
                                // find ascent / descent
6144 avox 1262
                                double hlcsize10=charStyle.fontSize() / 10.0;
9737 jghali 1263
                                if ((hl->ch == SpecialChars::OBJECT) && (hl->embedded.hasItem()))
5362 avox 1264
                                {
1265
                                        desc = desc2 = 0;
1266
                                }
1267
                                else
1268
                                {
6144 avox 1269
                                        desc = desc2 = -charStyle.font().descent(hlcsize10);
9737 jghali 1270
                                        current.rememberShrinkStretch(hl->ch, wide, style);
5362 avox 1271
                                }
6144 avox 1272
                                asce = charStyle.font().ascent(hlcsize10);
6366 avox 1273
//                              wide = wide * hl->glyph.scaleH;
5362 avox 1274
                        }
1275
                        fBorder = false;
5408 avox 1276
                        // end of col reached?
13085 jghali 1277
//                      qDebug() << QString("eocol? %1 + %2 + %3 > %4 -- asce=%5").arg(current.yPos).arg(extra.Bottom).arg(lineCorr).arg(Height).arg(asce);
8095 avox 1278
                        if (current.isEndOfCol())
5362 avox 1279
                        {
8095 avox 1280
                                current.column++;
1281
                                if (current.column < Cols)
5362 avox 1282
                                {
5408 avox 1283
                                        // start next col
8095 avox 1284
                                        current.nextColumn(asce);
5721 avox 1285
                                        if (((a > firstInFrame()) && (itemText.text(a-1) == SpecialChars::PARSEP))
1286
                                                || ((a == firstInFrame()) && (BackBox == 0)))
3614 cbradney 1287
                                        {
7313 avox 1288
                                                if (chstr[0] != SpecialChars::PARSEP)
5721 avox 1289
                                                        DropCmode = style.hasDropCap();
3614 cbradney 1290
                                                else
5362 avox 1291
                                                        DropCmode = false;
1292
                                                if (DropCmode)
3614 cbradney 1293
                                                {
8062 avox 1294
                                                        if (style.lineSpacingMode() == ParagraphStyle::BaselineGridLineSpacing)
6144 avox 1295
                                                                desc2 = -charStyle.font().descent() * m_Doc->typographicSettings.valueBaseGrid * style.dropCapLines();
3614 cbradney 1296
                                                        else
6805 avox 1297
                                                                desc2 = -charStyle.font().descent() * style.lineSpacing() * style.dropCapLines();
3614 cbradney 1298
                                                }
5362 avox 1299
                                                if (DropCmode)
5721 avox 1300
                                                        DropLines = style.dropCapLines();
3614 cbradney 1301
                                        }
13085 jghali 1302
//                                      qDebug() << QString("layout: nextcol grid=%1 x %2").arg(style.lineSpacingMode() == ParagraphStyle::BaselineGridLineSpacing).arg(m_Doc->typographicSettings.valueBaseGrid);
8062 avox 1303
                                        if (style.lineSpacingMode() == ParagraphStyle::BaselineGridLineSpacing)
3614 cbradney 1304
                                        {
5362 avox 1305
                                                double by = Ypos;
1306
                                                if (OwnPage != -1)
1307
                                                        by = Ypos - m_Doc->Pages->at(OwnPage)->yOffset();
8095 avox 1308
                                                int ol1 = qRound((by + current.yPos - m_Doc->typographicSettings.offsetBaseGrid) * 10000.0);
5362 avox 1309
                                                int ol2 = static_cast<int>(ol1 / m_Doc->typographicSettings.valueBaseGrid);
13085 jghali 1310
//                                              qDebug() << QString("baseline adjust: y=%1->%2").arg(current.yPos).arg(ceil(  ol2 / 10000.0 ) * m_Doc->typographicSettings.valueBaseGrid + m_Doc->typographicSettings.offsetBaseGrid - by);
8956 avox 1311
 
8095 avox 1312
                                                current.yPos = ceil(  ol2 / 10000.0 ) * m_Doc->typographicSettings.valueBaseGrid + m_Doc->typographicSettings.offsetBaseGrid - by;
3614 cbradney 1313
                                        }
5362 avox 1314
                                }
1315
                                else
1316
                                {
8095 avox 1317
                                        MaxChars = a;
13085 jghali 1318
//                                      qDebug() << QString("no room A: %1").arg(a);
5362 avox 1319
                                        goto NoRoom;
1320
                                }
1321
                        }
5408 avox 1322
                        // ok, there's more room in col
8095 avox 1323
                        if (current.itemsInLine == 0)
5362 avox 1324
                        {
13085 jghali 1325
//                              qDebug() << QString("newline: '%1' %2 %3").arg(a).arg(current.yPos).arg(asce);
5408 avox 1326
                                // start a new line
5362 avox 1327
                                double TopOffset = asce;
1328
                                double BotOffset = desc2;
1329
                                goNoRoom = false;
8095 avox 1330
                                if (current.startOfCol)
5362 avox 1331
                                {
13085 jghali 1332
//                                      qDebug() << QString("current.startOfCol: %1 + %2 + %3 + 1 =%4").arg(asce).arg(extra.Top).arg(lineCorr).arg(asce + extra.Top + lineCorr + 1);
8095 avox 1333
                                        current.yPos = asce + extra.Top + lineCorr + 1;
5408 avox 1334
//                                                      if (((a > 0) && (itemText.at(a-1)->ch == QChar(13))) || ((a == 0) && (BackBox == 0)))
8095 avox 1335
//                                                              current.yPos += m_Doc->docParagraphStyles[hl->cab].gapBefore;
5362 avox 1336
                                }
13085 jghali 1337
//                              qDebug() << QString("layout: nextline grid=%1 x %2").arg(style.lineSpacingMode() == ParagraphStyle::BaselineGridLineSpacing).arg(m_Doc->typographicSettings.valueBaseGrid);
8062 avox 1338
                                if (style.lineSpacingMode() == ParagraphStyle::BaselineGridLineSpacing)
5362 avox 1339
                                {
1340
                                        double by = Ypos;
1341
                                        if (OwnPage != -1)
1342
                                                by = Ypos - m_Doc->Pages->at(OwnPage)->yOffset();
8095 avox 1343
                                        int ol1 = qRound((by + current.yPos - m_Doc->typographicSettings.offsetBaseGrid) * 10000.0);
5362 avox 1344
                                        int ol2 = static_cast<int>(ol1 / m_Doc->typographicSettings.valueBaseGrid);
13085 jghali 1345
//                                      qDebug() << QString("useBaselIneGrid: %1 * %2 + %3 - %4").arg(ol2 / 10000.0).arg(m_Doc->typographicSettings.valueBaseGrid).arg(m_Doc->typographicSettings.offsetBaseGrid).arg(by);
1346
//                                      qDebug() << QString("baseline adjust: y=%1->%2").arg(current.yPos).arg(ceil(  ol2 / 10000.0 ) * m_Doc->typographicSettings.valueBaseGrid + m_Doc->typographicSettings.offsetBaseGrid - by);
8095 avox 1347
                                        current.yPos = ceil(  ol2 / 10000.0 ) * m_Doc->typographicSettings.valueBaseGrid + m_Doc->typographicSettings.offsetBaseGrid - by;
5362 avox 1348
                                }
8814 cbradney 1349
                                /* this causes different spacing for first line:
8095 avox 1350
                                if (current.yPos-TopOffset < 0.0)
8814 cbradney 1351
                                {
13085 jghali 1352
                                        qDebug(= << QString("current.yPos - Ascender < 0 (%1 - %2 < 0)").arg(current.yPos).arg(TopOffset);
8814 cbradney 1353
                                        current.yPos = TopOffset+1;
1354
                                }
1355
                                 */
5408 avox 1356
                                // find linelength:
8095 avox 1357
                                pt1 = QPoint(static_cast<int>(ceil(current.xPos)), static_cast<int>(current.yPos+BotOffset));
1358
                                pt2 = QPoint(static_cast<int>(ceil(current.xPos)), static_cast<int>(ceil(current.yPos-TopOffset)));
5408 avox 1359
                                // increase pt1/pt2 until i-beam reaches end of line
13085 jghali 1360
//                              qDebug() << QString("linestart: %1 + %2 + %3 < %4").arg(current.xPos).arg(wide).arg(style.rightMargin()).arg(current.colRight);
8095 avox 1361
                                double leftIndent = 0;
8127 avox 1362
                                double xStep = legacy? 1 : 0.125;
9372 fschmid 1363
                                while (!cl.contains(pf2.map(pt1)) || !cl.contains(pf2.map(pt2)) || current.isEndOfLine(wide + leftIndent + style.rightMargin()))
5362 avox 1364
                                {
1365
                                        fBorder = true;
8127 avox 1366
                                        current.xPos += xStep;
8095 avox 1367
                                        if (current.isEndOfLine(wide + leftIndent + style.rightMargin()))
3614 cbradney 1368
                                        {
13085 jghali 1369
//                                              qDebug() << QString("eocol %5? %1 + %2 + %3 + %4").arg(current.yPos).arg(current.startOfCol).arg(style.lineSpacingMode() == ParagraphStyle::BaselineGridLineSpacing).arg(style.lineSpacing()).arg(current.column);
5408 avox 1370
                                                // new line
5362 avox 1371
                                                fBorder = false;
8095 avox 1372
                                                current.xPos = current.colLeft;
1373
 
1374
                                                leftIndent = style.leftMargin();
1375
                                                if (a > 0 && itemText.text(a-1) == SpecialChars::PARSEP)
1376
                                                        leftIndent += style.firstIndent();
1377
 
1378
                                                if (current.startOfCol)
1379
                                                        current.yPos++;
5362 avox 1380
                                                else
12023 fschmid 1381
                                                        current.yPos += qMax(style.lineSpacing(), 1.0);
13085 jghali 1382
//                                              qDebug() << QString("layout: next lower line grid=%1 x %2").arg(style.lineSpacingMode() == ParagraphStyle::BaselineGridLineSpacing).arg(m_Doc->typographicSettings.valueBaseGrid);
8062 avox 1383
                                                if (style.lineSpacingMode() == ParagraphStyle::BaselineGridLineSpacing)
3614 cbradney 1384
                                                {
5362 avox 1385
                                                        double by = Ypos;
1386
                                                        if (OwnPage != -1)
1387
                                                                by = Ypos - m_Doc->Pages->at(OwnPage)->yOffset();
8095 avox 1388
                                                        int ol1 = qRound((by + current.yPos - m_Doc->typographicSettings.offsetBaseGrid) * 10000.0);
5362 avox 1389
                                                        int ol2 = static_cast<int>(ol1 / m_Doc->typographicSettings.valueBaseGrid);
13085 jghali 1390
//                                                      qDebug() << QString("baseline adjust: y=%1->%2").arg(current.yPos).arg(ceil(  ol2 / 10000.0 ) * m_Doc->typographicSettings.valueBaseGrid + m_Doc->typographicSettings.offsetBaseGrid - by);
8095 avox 1391
                                                        current.yPos = ceil(  ol2 / 10000.0 ) * m_Doc->typographicSettings.valueBaseGrid + m_Doc->typographicSettings.offsetBaseGrid - by;
5362 avox 1392
                                                }
8095 avox 1393
                                                if (current.isEndOfCol())
5362 avox 1394
                                                {
1395
                                                        fBorder = false;
8095 avox 1396
                                                        current.column++;
1397
                                                        if (current.column < Cols)
3614 cbradney 1398
                                                        {
8095 avox 1399
                                                                current.nextColumn(asce);
5721 avox 1400
                                                                if (((a > firstInFrame()) && (itemText.text(a-1) == SpecialChars::PARSEP)) || ((a == firstInFrame()) && (BackBox == 0)))
3614 cbradney 1401
                                                                {
7313 avox 1402
                                                                        if (chstr[0] != SpecialChars::PARSEP)
5721 avox 1403
                                                                                DropCmode = style.hasDropCap();
3614 cbradney 1404
                                                                        else
5362 avox 1405
                                                                                DropCmode = false;
1406
                                                                        if (DropCmode)
1407
                                                                        {
8062 avox 1408
                                                                                if (style.lineSpacingMode() == ParagraphStyle::BaselineGridLineSpacing)
6144 avox 1409
                                                                                        desc2 = -charStyle.font().descent() * m_Doc->typographicSettings.valueBaseGrid * style.dropCapLines();
5362 avox 1410
                                                                                else
6805 avox 1411
                                                                                        desc2 = -charStyle.font().descent() * style.lineSpacing() * style.dropCapLines();
5362 avox 1412
                                                                        }
1413
                                                                        if (DropCmode)
5721 avox 1414
                                                                                DropLines = style.dropCapLines();
3614 cbradney 1415
                                                                }
13085 jghali 1416
//                                                              qDebug() << QString("layout: nextcol2 grid=%1 x %2").arg(style.lineSpacingMode() == ParagraphStyle::BaselineGridLineSpacing).arg(m_Doc->typographicSettings.valueBaseGrid);
8062 avox 1417
                                                                if (style.lineSpacingMode() == ParagraphStyle::BaselineGridLineSpacing)
3614 cbradney 1418
                                                                {
5362 avox 1419
                                                                        double by = Ypos;
1420
                                                                        if (OwnPage != -1)
1421
                                                                                by = Ypos - m_Doc->Pages->at(OwnPage)->yOffset();
8095 avox 1422
                                                                        int ol1 = qRound((by + current.yPos - m_Doc->typographicSettings.offsetBaseGrid) * 10000.0);
5362 avox 1423
                                                                        int ol2 = static_cast<int>(ol1 / m_Doc->typographicSettings.valueBaseGrid);
13085 jghali 1424
//                                                                      qDebug() << QString("baseline adjust: y=%1->%2").arg(current.yPos).arg(ceil(  ol2 / 10000.0 ) * m_Doc->typographicSettings.valueBaseGrid + m_Doc->typographicSettings.offsetBaseGrid - by);
8095 avox 1425
                                                                        current.yPos = ceil(  ol2 / 10000.0 ) * m_Doc->typographicSettings.valueBaseGrid + m_Doc->typographicSettings.offsetBaseGrid - by;
3614 cbradney 1426
                                                                }
1427
                                                        }
1428
                                                        else
5362 avox 1429
                                                        {
8095 avox 1430
                                                                MaxChars = a;
13085 jghali 1431
//                                                              qDebug() << QString("no room B: %1").arg(a);
5362 avox 1432
                                                                goto NoRoom;
1433
                                                        }
3614 cbradney 1434
                                                }
5362 avox 1435
                                        }
8095 avox 1436
                                        pt1 = QPoint(static_cast<int>(ceil(current.xPos)), static_cast<int>(current.yPos+BotOffset));
1437
                                        pt2 = QPoint(static_cast<int>(ceil(current.xPos)), static_cast<int>(ceil(current.yPos-TopOffset)));
5362 avox 1438
                                }
5408 avox 1439
 
5362 avox 1440
                                if (((fBorder)) && (!AbsHasDrop))
8095 avox 1441
                                        current.xPos += extra.Left;
5408 avox 1442
                                // indent first line of par
5362 avox 1443
                                if (a > 0)
1444
                                {
5721 avox 1445
                                        if (itemText.text(a-1) == SpecialChars::PARSEP)
8095 avox 1446
                                                current.xPos += style.firstIndent();
5362 avox 1447
                                }
1448
                                else
1449
                                {
8814 cbradney 1450
                                        if (legacy)
8095 avox 1451
                                                current.xPos += style.firstIndent();
3614 cbradney 1452
                                }
5408 avox 1453
                                // add left margin
5362 avox 1454
                                if (!AbsHasDrop)
8095 avox 1455
                                        current.xPos += style.leftMargin();
1456
                                if (opticalMargins & ParagraphStyle::OM_LeftHangingPunct) {
1457
                                        current.xPos += opticalLeftMargin(itemText, current.line);
5390 avox 1458
                                }
13085 jghali 1459
//                              qDebug() << QString("store line: (%1,%2)").arg(current.xPos).arg(current.yPos);
8095 avox 1460
                                current.line.x = current.xPos;
1461
                                current.line.y = current.yPos;
5362 avox 1462
                                fBorder = false;
1463
                        }
6144 avox 1464
                        else {
13085 jghali 1465
//                              qDebug() << QString("cont.' line: '%1'").arg(a);
6144 avox 1466
                        }
5408 avox 1467
                        // right tab stuff
7905 avox 1468
                        if (tabs.active)
5362 avox 1469
                        {
9737 jghali 1470
                                if (((hl->ch == '.') && (tabs.status == TabPOINT)) || ((hl->ch == ',') && (tabs.status == TabCOMMA)) || (hl->ch == SpecialChars::TAB))
5362 avox 1471
                                {
7905 avox 1472
                                        tabs.active = false;
1473
                                        tabs.status = TabNONE;
3614 cbradney 1474
                                }
1475
                        }
5408 avox 1476
                        // tab positioning
9737 jghali 1477
                        if (hl->ch == SpecialChars::TAB)
3614 cbradney 1478
                        {
5362 avox 1479
                                wide = 1;
7905 avox 1480
                                if (tabs.active)
1481
                                        tabs.active = false;
1482
                                else // ???
3614 cbradney 1483
                                {
8095 avox 1484
                                        tabs.xPos = current.xPos;
5721 avox 1485
                                        tTabValues = style.tabValues();
5362 avox 1486
                                        if (tTabValues.isEmpty())
3614 cbradney 1487
                                        {
8095 avox 1488
                                                if ((current.xPos - current.colLeft) != 0)
3614 cbradney 1489
                                                {
8095 avox 1490
                                                        if (current.xPos == current.colLeft + ceil((current.xPos-current.colLeft) / m_Doc->toolSettings.dTabWidth) * m_Doc->toolSettings.dTabWidth)
1491
                                                                current.xPos += m_Doc->toolSettings.dTabWidth;
5362 avox 1492
                                                        else
8095 avox 1493
                                                                current.xPos = current.colLeft + ceil((current.xPos-current.colLeft) / m_Doc->toolSettings.dTabWidth) * m_Doc->toolSettings.dTabWidth;
3614 cbradney 1494
                                                }
5362 avox 1495
                                                else
8095 avox 1496
                                                        current.xPos = current.colLeft + m_Doc->toolSettings.dTabWidth;
7905 avox 1497
                                                tabs.status = TabNONE;
1498
                                                tabs.active = false;
3614 cbradney 1499
                                        }
5362 avox 1500
                                        else
1501
                                        {
8095 avox 1502
                                                double tCurX = current.xPos - current.colLeft;
5362 avox 1503
                                                double oCurX = tCurX + wide;
1504
                                                for (int yg = static_cast<int>(tTabValues.count()-1); yg > -1; yg--)
1505
                                                {
13406 jghali 1506
                                                        if (oCurX < tTabValues.at(yg).tabPosition)
5362 avox 1507
                                                        {
13406 jghali 1508
                                                                tabs.status = static_cast<int>(tTabValues.at(yg).tabType);
1509
                                                                tCurX = tTabValues.at(yg).tabPosition;
1510
                                                                tabs.fillChar = tTabValues.at(yg).tabFillChar;
5362 avox 1511
                                                        }
1512
                                                }
7905 avox 1513
                                                tabs.active = (tabs.status != TabLEFT);
5362 avox 1514
                                                if (tCurX == oCurX-wide)
8095 avox 1515
                                                        current.xPos = current.colLeft + ceil((current.xPos-current.colLeft) / m_Doc->toolSettings.dTabWidth) * m_Doc->toolSettings.dTabWidth;
5362 avox 1516
                                                else
8095 avox 1517
                                                        current.xPos = current.colLeft + tCurX;
7905 avox 1518
 
1519
                                                // remember fill char
13085 jghali 1520
//                                              qDebug() << QString("tab: %1 '%2'").arg(tCurX).arg(tabs.fillChar);
7905 avox 1521
                                                if (!tabs.fillChar.isNull()) {
13945 jghali 1522
                                                        hl->glyph.growWithTabLayout();
1523
                                                        TabLayout * tglyph = dynamic_cast<TabLayout*>(hl->glyph.more);
1524
                                                        if (tglyph)
1525
                                                        {
1526
                                                                tglyph->fillChar = tabs.fillChar;
1527
                                                                tglyph->glyph    = charStyle.font().char2CMap(tabs.fillChar);
1528
                                                                tglyph->yoffset  = hl->glyph.yoffset;
1529
                                                                tglyph->scaleV   = tglyph->scaleH = chs / charStyle.fontSize();
1530
                                                                tglyph->xadvance = 0;
1531
                                                        }
7905 avox 1532
                                                }
5362 avox 1533
                                        }
12084 jghali 1534
                                        current.xPos -= (legacy ? 1.0 : 0.0);
1535
                                        hl->glyph.xadvance = current.xPos + wide + kernVal - tabs.xPos;
8095 avox 1536
//                                      wide = current.xPos - RTabX;
7905 avox 1537
                                        tabs.charIndex = a;
3614 cbradney 1538
                                }
5362 avox 1539
                        }
1540
 
5408 avox 1541
                        // remember y pos
5362 avox 1542
                        if (DropCmode)
7313 avox 1543
                                hl->glyph.yoffset -= charStyle.font().realCharHeight(chstr[0], chsd / 10.0) - charStyle.font().realCharAscent(chstr[0], chsd / 10.0);
8095 avox 1544
 
1545
 
8103 avox 1546
                        // remember x pos
1547
                        double breakPos = current.xPos;
8095 avox 1548
 
7905 avox 1549
                        if (!tabs.active) // normal case
5362 avox 1550
                        {
8095 avox 1551
                                current.xPos += wide+kernVal;
5362 avox 1552
                        }
7905 avox 1553
                        else if (tabs.active && tabs.status == TabCENTER)       // center tab
5362 avox 1554
                        {
8095 avox 1555
                                current.xPos += (wide+kernVal) / 2;
8562 jghali 1556
                                current.xPos = qMax(current.xPos, current.colLeft);
5362 avox 1557
                        }
7905 avox 1558
                        else // other tabs.active                       
5362 avox 1559
                        {
8562 jghali 1560
                                current.xPos = qMax(current.xPos, current.colLeft);
12084 jghali 1561
                        }              
7231 avox 1562
 
7346 avox 1563
                        //FIXME: asce / desc set correctly?
8103 avox 1564
                        if (legacy &&
10550 avox 1565
                                (((hl->ch == '-' || (hl->effects() & ScStyle_HyphenationPossible)) && (current.hyphenCount < m_Doc->HyCount || m_Doc->HyCount == 0))  
1566
                                || hl->ch == SpecialChars::SHYPHEN))
5362 avox 1567
                        {
9737 jghali 1568
                                if (hl->effects() & ScStyle_HyphenationPossible || hl->ch == SpecialChars::SHYPHEN)
3614 cbradney 1569
                                {
9047 avox 1570
                                        pt1 = QPoint(qRound(ceil(current.xPos+extra.Right - current.maxShrink + charStyle.font().charWidth('-', charStyle.fontSize() / 10.0) * (charStyle.scaleH() / 1000.0))), qRound(current.yPos+desc));
1571
                                        pt2 = QPoint(qRound(ceil(current.xPos+extra.Right - current.maxShrink + charStyle.font().charWidth('-', charStyle.fontSize() / 10.0) * (charStyle.scaleH() / 1000.0))), qRound(ceil(current.yPos-asce)));
3614 cbradney 1572
                                }
5362 avox 1573
                                else
3614 cbradney 1574
                                {
9047 avox 1575
                                        pt1 = QPoint(qRound(ceil(current.xPos+extra.Right - current.maxShrink )), qRound(current.yPos+desc));
1576
                                        pt2 = QPoint(qRound(ceil(current.xPos+extra.Right - current.maxShrink )), qRound(ceil(current.yPos-asce)));
3614 cbradney 1577
                                }
5362 avox 1578
                        }
9737 jghali 1579
                        else if (!legacy && SpecialChars::isBreakingSpace(hl->ch))
8127 avox 1580
                        {
9047 avox 1581
                                pt1 = QPoint(qRound(ceil(breakPos + extra.Right - current.maxShrink )), qRound(current.yPos+desc));
1582
                                pt2 = QPoint(qRound(ceil(breakPos + extra.Right - current.maxShrink )), qRound(ceil(current.yPos-asce)));
8127 avox 1583
                        }
8103 avox 1584
                        else
5362 avox 1585
                        {
9057 fschmid 1586
                                pt1 = QPoint(qRound(ceil(current.xPos+extra.Right - current.maxShrink)), qRound(current.yPos+desc));
1587
                                pt2 = QPoint(qRound(ceil(current.xPos+extra.Right - current.maxShrink)), qRound(ceil(current.yPos-asce)));
5362 avox 1588
                        }
8127 avox 1589
 
5408 avox 1590
                        // test if end of line reached
9372 fschmid 1591
                        if ((!cl.contains(pf2.map(pt1))) || (!cl.contains(pf2.map(pt2))) || (legacy && current.isEndOfLine(style.rightMargin())))
5362 avox 1592
                                outs = true;
8095 avox 1593
                        if (current.isEndOfCol())
5362 avox 1594
                                outs = true;
9737 jghali 1595
                        if ((hl->ch == SpecialChars::FRAMEBREAK) && (a < itemText.length()-1))
5362 avox 1596
                                goNoRoom = true;
9737 jghali 1597
                        if ((hl->ch == SpecialChars::COLBREAK) && (Cols > 1))
5362 avox 1598
                                goNextColumn = true;
6144 avox 1599
 
8103 avox 1600
 
1601
                        // remember possible break
13169 jghali 1602
                        // #5783 : comment out "&& !outs" as this make it possible to perform a line break
1603
                        // before a space which contradicts unicode line breaking rules
1604
                        if ( (SpecialChars::isBreakingSpace(hl->ch) || hl->ch == SpecialChars::TAB) /*&& !outs*/)
8103 avox 1605
                        {
8177 avox 1606
                                if ( a == firstInFrame() || !SpecialChars::isBreakingSpace(itemText.text(a-1)) )
8103 avox 1607
                                {
8127 avox 1608
                                        current.rememberBreak(a, breakPos);
8103 avox 1609
                                }
1610
                        }
1611
 
1612
 
1613
                        // hyphenation
9737 jghali 1614
                        if (((hl->effects() & ScStyle_HyphenationPossible) || (hl->ch == '-') || hl->ch == SpecialChars::SHYPHEN) && (!outs) && !itemText.text(a-1).isSpace() )
8103 avox 1615
                        {
1616
                                breakPos = current.xPos;
9737 jghali 1617
                                if (hl->ch != '-')
8103 avox 1618
                                {
1619
                                        breakPos += charStyle.font().charWidth('-', charStyle.fontSize() / 10.0) * (charStyle.scaleH() / 1000.0);
1620
                                }
1621
 
1622
                                double rightHang = 0;
1623
                                if (opticalMargins & ParagraphStyle::OM_RightHangingPunct) {
1624
                                        rightHang = 0.7 * charStyle.font().realCharWidth('-', (charStyle.fontSize() / 10.0) * (charStyle.scaleH() / 1000.0));
1625
                                }
1626
 
8127 avox 1627
                                if (legacy || (breakPos - rightHang < current.colRight - style.rightMargin()))
8103 avox 1628
                                {
9737 jghali 1629
                                        if ((current.hyphenCount < m_Doc->HyCount) || (m_Doc->HyCount == 0) || hl->ch == SpecialChars::SHYPHEN)
8103 avox 1630
                                        {
1631
                                                current.rememberBreak(a, breakPos);
1632
                                        }
1633
                                }
1634
                        }
1635
 
1636
 
1637
                        ++current.itemsInLine;
1638
 
7905 avox 1639
                        if (tabs.active)
5362 avox 1640
                        {
1641
                                double cen = 1;
7905 avox 1642
                                if (tabs.status == TabCENTER)
5362 avox 1643
                                        cen = 2;
7231 avox 1644
 
7905 avox 1645
                                double newTabAdvance = itemText.item(tabs.charIndex)->glyph.xadvance - (wide+kernVal) / cen;
7231 avox 1646
 
1647
                                if (newTabAdvance >= 0) {
7905 avox 1648
                                        itemText.item(tabs.charIndex)->glyph.xadvance = newTabAdvance;
7231 avox 1649
                                }
1650
                                else {
7905 avox 1651
                                        tabs.active = false;
1652
                                        tabs.status = TabNONE;
7231 avox 1653
                                }
5362 avox 1654
                        }
8103 avox 1655
 
5362 avox 1656
                        if (DropCmode)
1657
                        {
1658
                                DropCmode = false;
1659
                                AbsHasDrop = true;
11776 jghali 1660
                                DropLinesCount = 0;
8095 avox 1661
                                maxDY = current.yPos;
1662
                                current.xPos += style.dropCapOffset();
7287 avox 1663
                                hl->glyph.xadvance += style.dropCapOffset();
13085 jghali 1664
//                              qDebug() << QString("dropcapoffset: %1 -> %2").arg(current.xPos-style.dropCapOffset()).arg(current.xPos);
8562 jghali 1665
                                current.xPos = qMax(current.xPos, current.colLeft);
8095 avox 1666
                                maxDX = current.xPos;
10284 fschmid 1667
                                QPolygon tcli(4);
8062 avox 1668
                                if (style.lineSpacingMode() == ParagraphStyle::BaselineGridLineSpacing)
5362 avox 1669
                                {
8095 avox 1670
                                        current.yPos -= m_Doc->typographicSettings.valueBaseGrid * (DropLines-1);
5362 avox 1671
                                        double by = Ypos;
1672
                                        if (OwnPage != -1)
1673
                                                by = Ypos - m_Doc->Pages->at(OwnPage)->yOffset();
8095 avox 1674
                                        int ol1 = qRound((by + current.yPos - m_Doc->typographicSettings.offsetBaseGrid) * 10000.0);
5362 avox 1675
                                        int ol2 = static_cast<int>(ol1 / m_Doc->typographicSettings.valueBaseGrid);
13085 jghali 1676
//                                      qDebug() << QString("baseline adjust after dropcaps: y=%1->%2").arg(current.yPos).arg(ceil(  ol2 / 10000.0 ) * m_Doc->typographicSettings.valueBaseGrid + m_Doc->typographicSettings.offsetBaseGrid - by);
8095 avox 1677
                                        current.yPos = ceil(  ol2 / 10000.0 ) * m_Doc->typographicSettings.valueBaseGrid + m_Doc->typographicSettings.offsetBaseGrid - by;
1678
                                        //FIXME: use current.colLeft instead of xOffset?
5691 avox 1679
                                        tcli.setPoint(0, QPoint(qRound(hl->glyph.xoffset), qRound(maxDY-DropLines*m_Doc->typographicSettings.valueBaseGrid)));
5362 avox 1680
                                        tcli.setPoint(1, QPoint(qRound(maxDX), qRound(maxDY-DropLines*m_Doc->typographicSettings.valueBaseGrid)));
1681
                                }
1682
                                else
1683
                                {
5721 avox 1684
                                        if (style.lineSpacingMode() == ParagraphStyle::FixedLineSpacing)
3614 cbradney 1685
                                        {
8095 avox 1686
                                                current.yPos -= style.lineSpacing() * (DropLines-1);
13085 jghali 1687
//                                              qDebug() << QString("after dropcaps: y=%1").arg(current.yPos);
6805 avox 1688
                                                tcli.setPoint(0, QPoint(qRound(hl->glyph.xoffset), qRound(maxDY - DropLines * style.lineSpacing())));
1689
                                                tcli.setPoint(1, QPoint(qRound(maxDX), qRound(maxDY-DropLines*style.lineSpacing())));
5362 avox 1690
                                        }
1691
                                        else
1692
                                        {
6144 avox 1693
                                                double currasce = charStyle.font().height(style.charStyle().fontSize() / 10.0);
8095 avox 1694
                                                current.yPos -= currasce * (DropLines-1);
13085 jghali 1695
//                                              qDebug() << QString("after dropcaps: y=%1").arg(current.yPos);
5691 avox 1696
                                                tcli.setPoint(0, QPoint(qRound(hl->glyph.xoffset), qRound(maxDY-DropLines*currasce)));
5362 avox 1697
                                                tcli.setPoint(1, QPoint(qRound(maxDX), qRound(maxDY-DropLines*currasce)));
1698
                                        }
1699
                                }
1700
                                tcli.setPoint(2, QPoint(qRound(maxDX), qRound(maxDY)));
5691 avox 1701
                                tcli.setPoint(3, QPoint(qRound(hl->glyph.xoffset), qRound(maxDY)));
11776 jghali 1702
                                // #6821 : the following two lines are causing bad text flow around drop caps 
1703
                                // in some case, discarding them put more emphasis on user control of line spacing
1704
                                /*cm = QRegion(pf2.map(tcli));
1705
                                cl = cl.subtract(cm);*/
8095 avox 1706
//                              current.yPos = maxDY;
5362 avox 1707
                        }
5408 avox 1708
                        // end of line
9737 jghali 1709
                        if ( SpecialChars::isBreak(hl->ch, Cols > 1) || (outs))
5362 avox 1710
                        {
7905 avox 1711
                                tabs.active = false;
1712
                                tabs.status = TabNONE;
9737 jghali 1713
                                if (SpecialChars::isBreak(hl->ch, Cols > 1))
5362 avox 1714
                                {
8095 avox 1715
                                        // find end of line
1716
                                        current.breakLine(itemText, a);
14533 jghali 1717
                                        EndX = current.endOfLine(cl, pf2, style.rightMargin());
8095 avox 1718
                                        current.finishLine(EndX);
1719
 
9047 avox 1720
//                                      if (style.alignment() != 0)
5362 avox 1721
                                        {
8095 avox 1722
                                                if (opticalMargins & ParagraphStyle::OM_RightHangingPunct)
1723
                                                        current.line.width += opticalRightMargin(itemText, current.line);
1724
 
1725
                                                OFs = 0;
12889 jghali 1726
                                                if (style.alignment() == ParagraphStyle::Rightaligned)
8095 avox 1727
                                                        OFs = current.line.width - current.line.naturalWidth;
12889 jghali 1728
                                                if (style.alignment() == ParagraphStyle::Centered)
8095 avox 1729
                                                        OFs = (current.line.width - current.line.naturalWidth) / 2;
12889 jghali 1730
                                                if (style.alignment() == ParagraphStyle::Justified)
5362 avox 1731
                                                        OFs = 0;
8095 avox 1732
 
12889 jghali 1733
                                                if (style.alignment() == ParagraphStyle::Extended
1734
                                                        || (style.alignment() == ParagraphStyle::Justified
9737 jghali 1735
                                                                &&  (hl->ch == SpecialChars::LINEBREAK ||
1736
                                                                         hl->ch == SpecialChars::FRAMEBREAK ||
1737
                                                                         hl->ch == SpecialChars::COLBREAK)
8095 avox 1738
                                                                &&  !itemText.text(current.line.lastItem - 1).isSpace()))
5362 avox 1739
                                                {
8095 avox 1740
                                                        justifyLine(itemText, current.line);
3614 cbradney 1741
                                                }
1742
                                                else
1743
                                                {
9047 avox 1744
                                                        if (opticalMargins & ParagraphStyle::OM_RightHangingPunct)
1745
                                                                current.line.naturalWidth += opticalRightMargin(itemText, current.line);
1746
                                                        double optiWidth = current.colRight - style.lineSpacing()/2.0 - current.line.x;
1747
                                                        if (current.line.naturalWidth > optiWidth)
10394 cbradney 1748
                                                                current.line.width = qMax(current.line.width - current.maxShrink, optiWidth);
5408 avox 1749
                                                        // simple offset
9047 avox 1750
                                                        indentLine(itemText, current.line, OFs);
3614 cbradney 1751
                                                }
9047 avox 1752
                                                current.xPos = current.colRight;
3614 cbradney 1753
                                        }
5362 avox 1754
                                }
8845 cbradney 1755
                                else // outs -- last char went outside the columns (or into flow-around shape)
5362 avox 1756
                                {
8095 avox 1757
                                        if (current.breakIndex >= 0)            // Hier koenen auch andere Trennungen eingebaut werden
3614 cbradney 1758
                                        {
5408 avox 1759
                                                // go back to last break position
13085 jghali 1760
//                                              qDebug() << QString("new break pos a=%1 BuPos=%2 current.breakIndex=%3").arg(a).arg(BuPos).arg(current.breakIndex);
8095 avox 1761
                                                a = current.breakIndex;
5980 avox 1762
                                                assert( a >= 0 );
1763
                                                assert( a < itemText.length() );
5721 avox 1764
                                                hl = itemText.item(a);
6805 avox 1765
                                                style = itemText.paragraphStyle(a);
8956 avox 1766
                                                if (style.lineSpacingMode() == ParagraphStyle::AutomaticLineSpacing)
1767
                                                {
1768
                                                        style.setLineSpacing(style.charStyle().font().height(style.charStyle().fontSize() / 10.0));
13085 jghali 1769
//                                                      qDebug() << QString("auto linespacing: %1").arg(style.lineSpacing());
8956 avox 1770
                                                }
11768 jghali 1771
                                                else if (style.lineSpacingMode() == ParagraphStyle::BaselineGridLineSpacing)
1772
                                                        style.setLineSpacing(m_Doc->typographicSettings.valueBaseGrid);
8095 avox 1773
                                                current.itemsInLine = a - current.line.firstItem + 1;
13085 jghali 1774
//                                              qDebug() << QString("style outs pos %1: %2 (%3)").arg(a).arg(style.alignment()).arg(style.parent());
1775
//                                              qDebug() << QString("style <@%6: %1 -- %2, %4/%5 char: %3").arg(style.leftMargin()).arg(style.rightMargin())
6805 avox 1776
//                                                         .arg(style.charStyle().asString()).arg(style.name()).arg(style.parent()?style.parent()->name():"")
13085 jghali 1777
//                                                         .arg(a);
7356 avox 1778
 
9737 jghali 1779
                                                if (hl->ch == ' ') {
7356 avox 1780
                                                        hl->setEffects(hl->effects() | ScStyle_SuppressSpace);
1781
                                                        hl->glyph.xadvance = 0;
1782
                                                }
6144 avox 1783
 
14734 jghali 1784
                                                current.updateHeightMetrics(itemText);
14533 jghali 1785
                                                EndX = current.endOfLine(cl, pf2, style.rightMargin());
8095 avox 1786
                                                current.finishLine(EndX);
1787
 
1788
//???                                           current.breakXPos = current.line.x;
1789
//???                                           for (int j=current.line.firstItem; j <= a; ++j)
1790
//???                                                   current.breakXPos += itemText.item(j)->glyph.wide();
1791
 
9737 jghali 1792
                                                if ((hl->effects() & ScStyle_HyphenationPossible) || hl->ch == SpecialChars::SHYPHEN)
3614 cbradney 1793
                                                {
5362 avox 1794
                                                        // insert hyphen
8095 avox 1795
                                                        current.hyphenCount++;
5691 avox 1796
                                                        hl->setEffects(hl->effects() | ScStyle_SmartHyphenVisible);
8095 avox 1797
                                                        hl->glyph.grow();
6144 avox 1798
                                                        hl->glyph.more->glyph = charStyle.font().char2CMap(QChar('-'));
1799
                                                        hl->glyph.more->xadvance = charStyle.font().charWidth('-', itemText.charStyle(a).fontSize() / 10.0) * (itemText.charStyle(a).scaleH() / 1000.0);
5362 avox 1800
                                                }
5408 avox 1801
                                                else