Index: scribus/pageitem_textframe.h =================================================================== --- scribus/pageitem_textframe.h (rvision 13613) +++ scribus/pageitem_textframe.h (copie de travail) @@ -103,6 +103,12 @@ void setShadow(); QString currentShadow; QMap shadows; + + double lastLineHash; + double scaleCacheControl; + QList selectCacheControl; + QList lineCacheControl; + QMap lineCache; private slots: void slotInvalidateLayout(); Index: scribus/pageitem_textframe.cpp =================================================================== --- scribus/pageitem_textframe.cpp (rvision 13613) +++ scribus/pageitem_textframe.cpp (copie de travail) @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -253,9 +254,9 @@ dumpIt(*dynamic_cast(pstyle.parentStyle()), more + indent); } +// 2009.06.08 is great day - pm +static const bool legacy = false; -static const bool legacy = true; - /* static void layoutDropCap(GlyphLayout layout, double curX, double curY, double offsetX, double offsetY, double dropCapDrop) { @@ -618,8 +619,41 @@ } return result; } - - + + void adjustLineHeight(const StoryText& itemText) + { + for(int idx(line.firstItem); idx <= line.lastItem; ++idx) + { + const ScText * c(itemText.item(idx)); + double rca(c->glyph.scaleV * itemText.charStyle(idx). + font(). + realCharAscent(itemText.text(idx), itemText.charStyle(idx).fontSize() / 10.0)); + double rcd(c->glyph.scaleV * itemText.charStyle(idx). + font(). + realCharDescent(itemText.text(idx), itemText.charStyle(idx).fontSize() / 10.0)); + line.ascent = qMax(line.ascent, c->glyph.yoffset + rca ); + line.descent = qMax(line.descent, rcd - c->glyph.yoffset ); + } + } + + double getLineHash(const StoryText& itemText, const LineSpec * linespec = 0) const + { + const LineSpec * ls(linespec ? linespec : &line); + double controlValue(ls->x); + double cc(1.0); + for(int cidx(ls->firstItem); cidx <= ls->lastItem; ++cidx) + { + const GlyphLayout glyt(itemText.item(cidx)->glyph); + controlValue += ((glyt.glyph != 0.0) ? glyt.glyph : 1.0) * cc * 2.0; + controlValue += ((glyt.scaleH != 0.0) ? glyt.scaleH : 1.0) * cc * 3.0; + controlValue += ((glyt.scaleV != 0.0) ? glyt.scaleV : 1.0) * cc * 4.0; + controlValue += ((glyt.xadvance != 0.0) ? glyt.xadvance : 1.0) * cc * 5.0; + controlValue += ((glyt.xoffset != 0.0) ? glyt.xoffset : 1.0) * cc * 6.0; + controlValue += ((glyt.yoffset != 0.0) ? glyt.yoffset : 1.0) * cc * 7.0; + cc *= 1.1; + } + return controlValue * ((ls->y != 0.0)? ls->y :1.0); + } private: double frameWidth; double frameHeight; @@ -829,6 +863,8 @@ if (invalid && BackBox == NULL) firstChar = 0; +// lineCacheControlOld = lineCacheControl; + lineCacheControl.clear(); // qDebug() << QString("textframe(%1,%2): len=%3, start relayout at %4").arg(Xpos).arg(Ypos).arg(itemText.length()).arg(firstInFrame()); // ScribusView* view = m_Doc->view(); QMatrix pf2; @@ -952,6 +988,8 @@ outs = false; OFs = 0; MaxChars = 0; +// qDebug()<<"Layout"<setEffects(itemText.item(a)->effects() & ~ScStyle_StartOfLine); } - hl->glyph.yadvance = 0; - oldCurY = layoutGlyphs(*hl, chstr, hl->glyph); + // I dont know exactly why but it does not respect the layout in all occasions +// if(((a >= itemText.invalidIntervalStart()) && (a < itemText.invalidIntervalEnd())) +// || (SpecialChars::isBreakingSpace(hl->ch) || hl->ch.isSpace()) ) + { + hl->glyph.yadvance = 0; + oldCurY = layoutGlyphs(*hl, chstr, hl->glyph); + } // find out width of char if ((hl->ch == SpecialChars::OBJECT) && (hl->embedded.hasItem())) wide = hl->embedded.getItem()->gWidth + hl->embedded.getItem()->lineWidth(); @@ -2075,7 +2118,18 @@ if (current.line.firstItem > current.line.lastItem) ; //qDebug() << QString("layout: empty line %1 - %2").arg(current.line.firstItem).arg(current.line.lastItem); else if (current.itemsInLine > 0) + { + current.adjustLineHeight(itemText); itemText.appendLine(current.line); + double hLine(current.getLineHash(itemText)); + if(!lineCacheControl.contains(hLine)) + { + lineCacheControl << hLine; + } + else + qDebug()<<"Ooops 2 lines with same hash!"<< hLine; + } + current.startLine(a+1); outs = false; if (goNoRoom) @@ -2248,7 +2302,15 @@ // .arg(current.line.x).arg(current.line.y).arg(current.line.naturalWidth).arg(current.line.width); if (current.itemsInLine > 0) { + current.adjustLineHeight(itemText); itemText.appendLine(current.line); + double hLine(current.getLineHash(itemText)); + if(!lineCacheControl.contains(hLine)) + { + lineCacheControl << hLine; + } + else + qDebug()<<"Ooops 2 lines with same hash!"<< hLine; } } MaxChars = itemText.length(); @@ -2257,21 +2319,35 @@ if (NextBox != NULL) { PageItem_TextFrame* nextFrame = dynamic_cast(NextBox); - if (nextFrame != NULL) + double currentLastLineHash(0); + if(itemText.length() > 0) + currentLastLineHash = current.getLineHash(itemText); + if ((nextFrame != NULL) + && (currentLastLineHash != lastLineHash)) { + lastLineHash = currentLastLineHash; nextFrame->invalid = true; nextFrame->firstChar = MaxChars; } } // qDebug("textframe: len=%d, done relayout", itemText.length()); + if(itemText.length() > 0) + lastLineHash = current.getLineHash(itemText); + else + lastLineHash = 0; return; NoRoom: // pf2.end(); invalid = false; PageItem_TextFrame * next = dynamic_cast(NextBox); - if (next != NULL) + double currentLastLineHash(0); + if(itemText.length() > 0) + currentLastLineHash = current.getLineHash(itemText); + if ((next != NULL) + && (currentLastLineHash != lastLineHash)) { + lastLineHash = currentLastLineHash; next->invalid = true; next->firstChar = MaxChars; if (CPos > signed(MaxChars)) @@ -2301,12 +2377,10 @@ this->invalid = true; if (wholeChain) { - PageItem *prevFrame = this->prevInChain(); - while (prevFrame != 0) - { - prevFrame->invalid = true; - prevFrame = prevFrame->prevInChain(); - } + // lets see if it could work. I can be wrong, but I have the idea that something changed in a frame _cannot_ alters the previous frame in the string. So its not the place to invalidate it. +// PageItem *prevFrame = this->prevInChain(); +// if (prevFrame != 0) +// prevFrame->invalid = true; PageItem *nextFrame = this->nextInChain(); while (nextFrame != 0) { @@ -2318,10 +2392,40 @@ void PageItem_TextFrame::DrawObj_Item(ScPainter *p, QRectF cullingArea, double sc) { + QTime t,tt; + t.start(); + int dl(0); + int dg(0); + int dgdg(0); + + QList usedCached; + QList selectLines; + QMap coorX; + QMap coorY; + QMap lHeight; + + if(sc != scaleCacheControl) + { + scaleCacheControl = sc; + foreach(const double& ik, lineCache.keys()) + { + delete lineCache[ik]; + } + lineCache.clear(); + } + if(invalid) + { layout(); + itemText.resetInvalidInterval(); + dl = t.elapsed(); + } if (invalid) + { + qDebug()<<"Layout of"<glyph.wide(); } if(!selectedFrame.isNull()) + { sFList << selectedFrame; + lineCacheControl.removeAll(hLine); + selectLines << hLine; + } + // We need to invalidate lines which were just deselected + foreach(const double& ik, selectCacheControl) + { + if(!selectLines.contains(ik) + && lineCache.contains(ik)) + { + delete lineCache[ik]; + lineCache.remove(ik); + } + } + selectCacheControl = selectLines; + p->save();//SA3 p->setFillMode(1); p->setBrush(qApp->palette().color(QPalette::Active, QPalette::Highlight)); @@ -2498,6 +2620,39 @@ p->restore();//RE3 // End of selection + // cached + +// qDebug()<<"HLine"<fill(Qt::transparent); + ScPainter cachepainter(lineCache[hLine], lineCache[hLine]->width() , lineCache[hLine]->height()); + ScPainter *sp(&cachepainter); + sp->scale(sc,sc); + coorX[hLine] = ls.x; + coorY[hLine] = ls.y; + lHeight[hLine] = intLineAscent; +// qDebug()<<"\tLine"<<"\tsc:"<setFillMode(ScPainter::Solid); + sp->setFillMode(ScPainter::Solid); if ((cachedFillShade != actFillShade) || (cachedFill != actFill)) { SetQColor(&tmp, actFill, actFillShade); - p->setBrush(tmp); + sp->setBrush(tmp); cachedFillQ = tmp; cachedFill = actFill; cachedFillShade = actFillShade; } else - p->setBrush(cachedFillQ); + sp->setBrush(cachedFillQ); } else - p->setFillMode(ScPainter::None); + sp->setFillMode(ScPainter::None); if (charStyle.effects() & ScStyle_DropCap) { const ParagraphStyle& style(itemText.paragraphStyle(a)); @@ -2553,7 +2708,7 @@ if (((selected && Select) || ((NextBox != 0 || BackBox != 0) && selected)) && (m_Doc->appMode == modeEdit)) { // set text color to highlight if its selected - p->setBrush(qApp->palette().color(QPalette::Active, QPalette::HighlightedText)); + sp->setBrush(qApp->palette().color(QPalette::Active, QPalette::HighlightedText)); } actStroke = charStyle.strokeColor(); @@ -2563,24 +2718,29 @@ if ((cachedStrokeShade != actStrokeShade) || (cachedStroke != actStroke)) { SetQColor(&tmp, actStroke, actStrokeShade); - p->setPen(tmp, 1, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin); + sp->setPen(tmp, 1, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin); cachedStrokeQ = tmp; cachedStroke = actStroke; cachedStrokeShade = actStrokeShade; } else - p->setPen(cachedStrokeQ, 1, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin); + sp->setPen(cachedStrokeQ, 1, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin); } // paint glyphs if (cullingArea.intersects(pf2.mapRect(QRect(qRound(CurX + hl->glyph.xoffset),qRound(ls.y + hl->glyph.yoffset-asce), qRound(hl->glyph.xadvance+1), qRound(asce+desc))))) { - p->save();//SA4 - p->translate(CurX, ls.y); + usedCached << hLine; + tt.restart(); + sp->save();//SA4 +// sp->translate(CurX, ls.y); + sp->translate(CurX, intLineAscent); if (hl->ch == SpecialChars::OBJECT) - DrawObj_Embedded(p, cullingArea, charStyle, hl->embedded.getItem()); + DrawObj_Embedded(sp, cullingArea, charStyle, hl->embedded.getItem()); else - drawGlyphs(p, charStyle, hl->glyph); - p->restore();//RE4 + drawGlyphs(sp, charStyle, hl->glyph); + sp->restore();//RE4 + dg += tt.elapsed(); + ++dgdg; } if (hl->ch == SpecialChars::OBJECT) CurX += (hl->embedded.getItem()->gWidth + hl->embedded.getItem()->lineWidth()) * hl->glyph.scaleH; @@ -2595,7 +2755,33 @@ // } // pf2.end(); } + +// Commit lines images to argued device + if(itemText.lines() > 0) + { + p->save(); + p->scale(1.0/sc,1.0/sc); + foreach(const double& ik, lineCache.keys()) + { + if(usedCached.contains(ik)) + { + double stripYPos((coorY[ik]*sc) - (lHeight[ik]*sc)); + double stripXPos(coorX[ik] * sc); + + p->translate(stripXPos, stripYPos); + p->drawImage(lineCache[ik]); + p->translate(-stripXPos, -stripYPos); + } + else + { + delete lineCache[ik]; + lineCache.remove(ik); + } + } + p->restore(); + } p->restore();//RE1 + qDebug()<<"Text Drawing"<