All pastes #1452165 Raw Edit

drawtext perfs mini

public diff v1 · immutable
#1452165 ·published 2009-06-08 18:53 UTC
rendered paste body
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<QString,StoryText> shadows;++	double lastLineHash;+	double scaleCacheControl;+	QList<double> selectCacheControl;+	QList<double> lineCacheControl;+	QMap<double, QImage*> 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 <QPoint> #include <QPolygon> #include <QRegion>+#include <QTime> #include <cassert> #include <cmath> @@ -253,9 +254,9 @@ 		dumpIt(*dynamic_cast<const ParagraphStyle*>(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"<<itemName()<<firstInFrame()<<itemText.length()+//				<<"\n\tClip"<< (&itemText) << itemText.invalidIntervalStart()<<itemText.invalidIntervalEnd(); 		for (int a = firstInFrame(); a < itemText.length(); ++a) 		{ 			hl = itemText.item(a);@@ -1125,8 +1163,13 @@ 				kernVal = 0; // chs * charStyle.tracking() / 10000.0; 				itemText.item(a)->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<PageItem_TextFrame*>(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<PageItem_TextFrame*>(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<double> usedCached;+	QList<double> selectLines;+	QMap<double, double> coorX;+	QMap<double, double> coorY;+	QMap<double, double> 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"<<itemName()<<"did not fix invalidity"; 		return;+	}+ 	QMatrix pf2; 	QPoint pt1, pt2; 	double wide, lineCorr;@@ -2431,8 +2535,10 @@ 		for (uint ll=0; ll < itemText.lines(); ++ll) 		{ 			ls = itemText.line(ll);+			double hLine(LineControl().getLineHash(itemText, &ls)); 			tabDist = ls.x;-			double CurX = ls.x;+//			double CurX = ls.x;+			double CurX(0.0);  			// Draw text selection rectangles 			QRectF selectedFrame;@@ -2484,7 +2590,23 @@ 					selX += hls->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"<<ls.y<<hLine;+			if(lineCacheControl.contains(hLine) && lineCache.contains(hLine))+			{+//				qDebug()<<"Skip painting of"<<ls.y<<hLine;+				coorX[hLine] = ls.x;+				coorY[hLine] = ls.y;+				lHeight[hLine] = ceil(ls.ascent);+				usedCached << hLine;+				continue;+			}+			else if(lineCache.contains(hLine))+			{+				delete lineCache[hLine];+//				qDebug()<<"Deleted line cache image"<<hLine;+			}+			int intLineAscent(ceil(ls.ascent));+			int intScaledLineAscent(ceil(ls.ascent * sc ));+			int intScaledLineHeight(ceil(ls.descent * sc ) + intScaledLineAscent );+			lineCache[hLine] = new QImage(ceil( ls.width * sc  ), intScaledLineHeight , QImage::Format_ARGB32);+			lineCache[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:"<<sc<<"\ty:"<<ls.y<<"\tasc:"<<ls.ascent<<"\tdesc:"<<ls.descent+//					<<"\n\t\tISAsc:"<<intScaledLineAscent<<"\tISDesc:"<< ceil(ls.descent * sc ) << "\tSH:"<<intScaledLineHeight ;++			// end of cached+ 			QColor tmp; 			ScText *hl = 0; 			for (int a = ls.firstItem; a <= qMin(ls.lastItem, itemText.length()); ++a)@@ -2513,20 +2668,20 @@ 				actFillShade = charStyle.fillShade(); 				if (actFill != CommonStrings::None) 				{-					p->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"<<t.elapsed()<<"ms; layout"<<dl<<"ms;"<< dg <<"ms actually drawing"<<dgdg<<"items, thus"<< (double(dg) / double(dgdg)) <<"ms/item"; }  void PageItem_TextFrame::DrawObj_Post(ScPainter *p)