r16988 by jghali - #10385 (second part) : improve text layout stability of rotated frames

scribus-commit scribus-commit at lists.scribus.net
Sat Nov 19 12:54:45 UTC 2011


Author: jghali
Date: Sat Nov 19 12:54:45 2011
New Revision: 16988

URL: http://scribus.net/websvn/listing.php?repname=Scribus&sc=1&rev=16988
Log:
#10385 (second part) : improve text layout stability of rotated frames
PageItem::availableRegion() has been changed to compute the available region in PageItem local coordinates. As a consequence that region does not change if frame is rotated and result in same layout being computed whether frame is rotated or not. As text layout is now fully computed using PageItem local coordinates, a few map() calls have been removed from layout() : as a consequence of reduced memory allocations, we get a speed improvements of around 17% of layout() function.

Modified:
    branches/Version135/Scribus/scribus/pageitem_textframe.cpp
    branches/Version135/Scribus/scribus/pageitem_textframe.h

Modified: branches/Version135/Scribus/scribus/pageitem_textframe.cpp
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=16988&path=/branches/Version135/Scribus/scribus/pageitem_textframe.cpp
==============================================================================
--- branches/Version135/Scribus/scribus/pageitem_textframe.cpp (original)
+++ branches/Version135/Scribus/scribus/pageitem_textframe.cpp Sat Nov 19 12:54:45 2011
@@ -90,7 +90,6 @@
 {
 	QRegion res;
 	QMatrix pp;
-//	pp.begin(view->viewport());
 	pp.translate(docItem->xPos() - xOffset, docItem->yPos() - yOffset);
 	pp.rotate(docItem->rotation());
 	if (docItem->textFlowUsesBoundingBox())
@@ -100,35 +99,38 @@
 		tcli.setPoint(1, QPoint(qRound(docItem->width()), 0));
 		tcli.setPoint(2, QPoint(qRound(docItem->width()), qRound(docItem->height())));
 		tcli.setPoint(3, QPoint(0, qRound(docItem->height())));
-//		res = QRegion(pp.xForm(tcli));
 		res = QRegion(pp.map(tcli));
 	}
 	else if ((docItem->textFlowUsesImageClipping()) && (docItem->imageClip.size() != 0))
 	{
 		QList<uint> Segs;
 		QPolygon Clip2 = FlattenPath(docItem->imageClip, Segs);
-//		res = QRegion(pp.xForm(Clip2));
 		res = QRegion(pp.map(Clip2)).intersect(QRegion(pp.map(docItem->Clip)));
 	}
 	else if ((docItem->textFlowUsesContourLine()) && (docItem->ContourLine.size() != 0))
 	{
 		QList<uint> Segs;
 		QPolygon Clip2 = FlattenPath(docItem->ContourLine, Segs);
-//		res = QRegion(pp.xForm(Clip2));
 		res = QRegion(pp.map(Clip2));
 	}
 	else
-//		res = QRegion(pp.xForm(docItem->Clip));
 		res = QRegion(pp.map(docItem->Clip));
-//	pp.end();
 	return  res;
 }
 
-QRegion PageItem_TextFrame::availableRegion(QRegion clip)
+QRegion PageItem_TextFrame::availableRegion()
 {
-	QRegion result(clip);
+	QRegion result(this->Clip);
 	if (!isEmbedded)
 	{
+		bool invertible(false);
+		QMatrix canvasToLocalMat;
+		canvasToLocalMat.translate(Xpos, Ypos);
+		canvasToLocalMat.rotate(Rot);
+		canvasToLocalMat = canvasToLocalMat.inverted(&invertible);
+
+		if (!invertible) return QRegion();
+
 		int LayerLev = m_Doc->layerLevelFromNumber(LayerNr);
 		uint docItemsCount=m_Doc->Items->count();
 		Page* Mp=0;
@@ -153,7 +155,10 @@
 					if ((currentGroup != -1) && (docItem->Groups.count() != 0) && (currentGroup == docItem->Groups.top()))
 						continue;
 					if (docItem->textFlowAroundObject())
-						result = result.subtracted(itemShape(docItem, Mp->xOffset() - Dp->xOffset(), Mp->yOffset() - Dp->yOffset()));
+					{
+						QRegion itemRgn = itemShape(docItem, Mp->xOffset() - Dp->xOffset(), Mp->yOffset() - Dp->yOffset());
+						result = result.subtracted( canvasToLocalMat.map(itemRgn) );
+					}
 					if (docItem->isGroupControl)
 						currentGroup = docItem->Groups.top();
 				}
@@ -188,7 +193,10 @@
 					if ((currentGroup != -1) && (docItem->Groups.count() != 0) && (currentGroup == docItem->Groups.top()))
 						continue;
 					if (docItem->textFlowAroundObject())
-						result = result.subtracted(itemShape(docItem, 0, 0));
+					{
+						QRegion itemRgn = itemShape(docItem, 0, 0);
+						result = result.subtracted( canvasToLocalMat.map(itemRgn) );
+					}
 					if (docItem->isGroupControl)
 						currentGroup = docItem->Groups.top();
 				}
@@ -540,7 +548,7 @@
 	}*/
 
 	/// find x position where this line must end
-	double endOfLine(const QRegion& shape, const QMatrix& pf2, double morespace, int yAsc, int yDesc)
+	double endOfLine(const QRegion& shape, double morespace, int yAsc, int yDesc)
 	{
 		// if we aren't restricted further, we'll end at this maxX:
 		double maxX = colRight - morespace;
@@ -553,10 +561,10 @@
 		QPoint  pt22 (xPos, yDesc);
 
 		QPolygon p;
-		p.append (pf2.map (QPoint (StartX, yAsc)));
-		p.append (pf2.map (QPoint (StartX, yDesc)));
-		p.append (pf2.map (pt12));
-		p.append (pf2.map (pt22));
+		p.append (QPoint (StartX, yAsc));
+		p.append (QPoint (StartX, yDesc));
+		p.append (pt12);
+		p.append (pt22);
 		// check if something gets in the way
 		QRegion lineI = shape.intersected (p.boundingRect());
 		// if the intersection only has 1 rectangle, then nothing gets in the way
@@ -564,10 +572,10 @@
 		{
 			int   cPos = static_cast<int>(ceil(StartX + morespace));
 			QRect cRect (QPoint(cPos, yAsc), QPoint(cPos, yDesc));
-			if (QRegion(pf2.mapToPolygon(cRect)).subtracted(shape).isEmpty())
+			if (QRegion(cRect).subtracted(shape).isEmpty())
 			{
 				QRect rect = lineI.rects().at(0);
-				double  mx = qMax(rect.left(), rect.right()) - pf2.dx(); 
+				double  mx = qMax(rect.left(), rect.right()) /*- pf2.dx()*/; 
 				int steps  = static_cast<int>((mx - StartX - morespace - 2) / 0.25);
 				if (steps > 0)
 				{
@@ -584,7 +592,7 @@
 		do {
 			int xP = static_cast<int>(ceil(EndX2 + morespace));
 			pt.moveTopLeft(QPoint(xP, yAsc));
-			region = QRegion(pf2.mapToPolygon(pt)).subtracted(shape);
+			region = QRegion(pt).subtracted(shape);
 			if (!region.isEmpty())
 				break;
 			EndX2 += Interval;
@@ -952,13 +960,13 @@
 	return 0.0;
 }
 
-static double findRealOverflowEnd(const QRegion& shape, const QMatrix& pf2, QRect pt, double maxX)
+static double findRealOverflowEnd(const QRegion& shape, QRect pt, double maxX)
 {
-	while (!QRegion(pf2.mapToPolygon(pt)).subtracted(shape).isEmpty() && pt.right() < maxX)
+	while (!QRegion(pt).subtracted(shape).isEmpty() && pt.right() < maxX)
 		pt.translate(1, 0);
 	if (pt.right() >= maxX)
 		return maxX;
-	return pt.left() +0.5;
+	return pt.left() + 0.5;
 }
 
 void PageItem_TextFrame::layout() 
@@ -991,7 +999,6 @@
 		firstChar = 0;
 	
 //	qDebug() << QString("textframe(%1,%2): len=%3, start relayout at %4").arg(Xpos).arg(Ypos).arg(itemText.length()).arg(firstInFrame());
-	QMatrix pf2;
 	QPoint pt1, pt2;
 	QRect pt;
 	double chs, chsd = 0;
@@ -1052,31 +1059,33 @@
 	}
 	qDebug() << "default:";
 	dumpIt(itemText.defaultStyle());
-*/	
-	
-	pf2.translate(Xpos, Ypos);
-	pf2.rotate(Rot);
+*/
 	
 	setShadow();
 	if ((itemText.length() != 0)) // || (NextBox != 0))
 	{
 		// determine layout area
-		QRegion cl = availableRegion(QRegion(pf2.map(Clip)));
+		QRegion cl = availableRegion();
 		if (cl.isEmpty())
 		{
 			MaxChars = firstInFrame();
 			goto NoRoom;
 		}
 		
-		if (imageFlippedH())
-		{
-			pf2.translate(Width, 0);
-			pf2.scale(-1, 1);
-		}
-		if (imageFlippedV())
-		{
-			pf2.translate(0, Height);
-			pf2.scale(1, -1);
+		if (imageFlippedH() || imageFlippedV())
+		{
+			QMatrix matrix;
+			if (imageFlippedH())
+			{
+				matrix.translate(Width, 0);
+				matrix.scale(-1, 1);
+			}
+			if (imageFlippedV())
+			{
+				matrix.translate(0, Height);
+				matrix.scale(1, -1);
+			}
+			cl = matrix.map(cl);
 		}
 		
 		current.nextColumn();
@@ -1486,9 +1495,9 @@
 					//check if in indent any overflow occurs
 					while (Xpos <= Xend && Xpos < current.colRight)
 					{
-						if (!QRegion(pf2.mapToPolygon(pt)).subtracted(cl).isEmpty())
+						if (!QRegion(pt).subtracted(cl).isEmpty())
 						{
-							Xpos = current.xPos = realEnd = findRealOverflowEnd(cl, pf2, pt, current.colRight);
+							Xpos = current.xPos = realEnd = findRealOverflowEnd(cl, pt, current.colRight);
 							Xend = current.xPos + current.leftIndent;
 						}
 						else
@@ -1815,9 +1824,9 @@
 					pt2 = QPoint(charEnd, maxYDesc);
 				}
 				pt = QRect(pt1, pt2);
-				if (!QRegion(pf2.mapToPolygon(pt)).subtracted(cl).isEmpty())
-				{
-					realEnd = findRealOverflowEnd(cl, pf2, pt, current.colRight);
+				if (!QRegion(pt).subtracted(cl).isEmpty())
+				{
+					realEnd = findRealOverflowEnd(cl, pt, current.colRight);
 					outs = true;
 				}
 				else if (style.rightMargin() > 0.0)
@@ -1826,9 +1835,9 @@
 						//condition after || is for find overflows in right margin area
 					{
 						pt.translate(static_cast<int>(ceil(style.rightMargin())), 0);
-						if (!QRegion(pf2.mapToPolygon(pt)).subtracted(cl).isEmpty())
+						if (!QRegion(pt).subtracted(cl).isEmpty())
 						{
-							realEnd = findRealOverflowEnd(cl, pf2, pt, current.colRight);
+							realEnd = findRealOverflowEnd(cl, pt, current.colRight);
 							outs = true;
 						}
 					}
@@ -1983,7 +1992,7 @@
 				{
 					// find end of line
 					current.breakLine(itemText, style, firstLineOffset(), a);
-					EndX = current.endOfLine(cl, pf2, style.rightMargin(), maxYAsc, maxYDesc);
+					EndX = current.endOfLine(cl, style.rightMargin(), maxYAsc, maxYDesc);
 					current.finishLine(EndX);
 					//addLine = true;
 					assert(current.addLine);
@@ -2060,7 +2069,7 @@
 						current.updateHeightMetrics(itemText);
 						//current.updateLineOffset(itemText, style, firstLineOffset());
 						//current.xPos = current.breakXPos;
-						EndX = current.endOfLine(cl, pf2, current.rightMargin, maxYAsc, maxYDesc);
+						EndX = current.endOfLine(cl, current.rightMargin, maxYAsc, maxYDesc);
 						current.finishLine(EndX);
 						
 						hyphWidth = 0.0;
@@ -2293,7 +2302,7 @@
 				maxYAsc = static_cast<int>(floor(current.yPos - qMax(realAsce, asce)));
 			maxYDesc = static_cast<int>(ceil(current.yPos + qMax(realDesc, desc)));
 
-			EndX = current.endOfLine(cl, pf2, style.rightMargin(), maxYAsc, maxYDesc);
+			EndX = current.endOfLine(cl, style.rightMargin(), maxYAsc, maxYDesc);
 			current.finishLine(EndX);
 
 			if (opticalMargins & ParagraphStyle::OM_RightHangingPunct)
@@ -2337,7 +2346,6 @@
 	}
 	MaxChars = itemText.length();
 	invalid = false;
-//	pf2.end();
 	if (NextBox != NULL) 
 	{
 		PageItem_TextFrame* nextFrame = dynamic_cast<PageItem_TextFrame*>(NextBox);
@@ -2351,7 +2359,6 @@
 	return;
 			
 NoRoom:     
-//	pf2.end();
 	invalid = false;
 	PageItem_TextFrame * next = dynamic_cast<PageItem_TextFrame*>(NextBox);
 	if (next != NULL)

Modified: branches/Version135/Scribus/scribus/pageitem_textframe.h
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=16988&path=/branches/Version135/Scribus/scribus/pageitem_textframe.h
==============================================================================
--- branches/Version135/Scribus/scribus/pageitem_textframe.h (original)
+++ branches/Version135/Scribus/scribus/pageitem_textframe.h Sat Nov 19 12:54:45 2011
@@ -85,7 +85,7 @@
 	void drawOverflowMarker(ScPainter *p);
 	void drawUnderflowMarker(ScPainter *p);
 	void drawColumnBorders(ScPainter *p);
-	QRegion availableRegion(QRegion clip);
+	QRegion availableRegion();
 
 #ifdef NLS_PROTO
 	void DrawLineItem(ScPainter *p, double width,




More information about the scribus-commit mailing list