View Issue Details

IDProjectCategoryView StatusLast Update
0016085ScribusPDFpublic2020-08-11 20:56
ReporterPontobart Assigned Tojghali  
PrioritynormalSeverityminorReproducibilityalways
Status closedResolutionfixed 
Product Version1.5.6.svn 
Fixed in Version1.5.6.svn 
Summary0016085: Add support for clipping along text paths
DescriptionThe attached patch fixes the following document: https://github.com/mozilla/pdf.js/blob/master/test/pdfs/ShowText-ShadingPattern.pdf (The preview on github is broken)

- It collects the shapes of the characters in a text group and applies the combined clip path at the end.
- In addition the handling of axial shading fills now considers rotation.
TagsNo tags attached.
PatchYes

Activities

Pontobart

2020-04-11 13:25

reporter  

add_text_clip.diff (5,092 bytes)   
Index: scribus/plugins/import/pdf/slaoutput.cpp
===================================================================
--- scribus/plugins/import/pdf/slaoutput.cpp	(Revision 23587)
+++ scribus/plugins/import/pdf/slaoutput.cpp	(Arbeitskopie)
@@ -1846,6 +1846,15 @@
 	state->getClipBBox(&xmin, &ymin, &xmax, &ymax);
 	QRectF crect = QRectF(QPointF(xmin, ymin), QPointF(xmax, ymax));
 	crect = crect.normalized();
+	QPainterPath out;
+	out.addRect(crect);
+	if (checkClip())
+	{
+		// Apply the clip path early to adjust the gradient vector to the
+		// smaller boundign box.
+		out = intersection(m_currentClipPath, out);
+		crect = out.boundingRect();
+	}
 	const double *ctm = state->getCTM();
 	m_ctm = QTransform(ctm[0], ctm[1], ctm[2], ctm[3], ctm[4], ctm[5]);
 	FPointArray gr;
@@ -1852,10 +1861,22 @@
 	gr.addPoint(GrStartX, GrStartY);
 	gr.addPoint(GrEndX, GrEndY);
 	gr.map(m_ctm);
-	GrStartX = gr.point(0).x() - crect.x();
-	GrStartY = gr.point(0).y() - crect.y();
-	GrEndX = gr.point(1).x() - crect.x();
-	GrEndY = gr.point(1).y() - crect.y();
+	gr.translate(-crect.x(), -crect.y());
+
+	// Undo the rotation and translation of the gradient vector.
+	double angle = m_ctm.map(QLineF(0, 0, 1, 0)).angle();
+	QTransform mm;
+	mm.rotate(angle);
+	out.translate(-crect.x(), -crect.y());
+	out = mm.map(out);
+	QRectF bb = out.boundingRect();
+	gr.map(mm);
+	gr.translate(-bb.left(), -bb.top());
+	GrStartX = gr.point(0).x();
+	GrStartY = gr.point(0).y();
+	GrEndX = gr.point(1).x();
+	GrEndY = gr.point(1).y();
+
 	double xCoor = m_doc->currentPage()->xOffset();
 	double yCoor = m_doc->currentPage()->yOffset();
 	QString output = QString("M %1 %2").arg(0.0).arg(0.0);
@@ -1866,16 +1887,14 @@
 	output += QString("Z");
 	pathIsClosed = true;
 	Coords = output;
-	int z = m_doc->itemAdd(PageItem::Polygon, PageItem::Rectangle, xCoor + crect.x(), yCoor + crect.y(), crect.width(), crect.height(), 0, CurrColorFill, CommonStrings::None);
+	int z = m_doc->itemAdd(PageItem::Polygon, PageItem::Rectangle, xCoor + crect.x(), yCoor + crect.y(), bb.width(), bb.height(), 0, CurrColorFill, CommonStrings::None);
 	PageItem* ite = m_doc->Items->at(z);
 	if (checkClip())
 	{
-		QPainterPath out = m_currentClipPath;
-		out.translate(m_doc->currentPage()->xOffset(), m_doc->currentPage()->yOffset());
-		out.translate(-ite->xPos(), -ite->yPos());
 		ite->PoLine.fromQPainterPath(out, true);
 		ite->setFillEvenOdd(out.fillRule() == Qt::OddEvenFill);
 	}
+	ite->setRotation(-angle);
 	ite->ClipEdited = true;
 	ite->FrameType = 3;
 	ite->setFillShade(CurrFillShade);
@@ -3203,7 +3222,7 @@
 
 void SlaOutputDev::drawChar(GfxState *state, double x, double y, double dx, double dy, double originX, double originY, CharCode code, int nBytes, POPPLER_CONST_082 Unicode *u, int uLen)
 {
-//	qDebug() << "SlaOutputDev::drawChar code:" << code << "bytes:" << nBytes << "Unicode:" << u << "ulen:" << uLen;
+//	qDebug() << "SlaOutputDev::drawChar code:" << code << "bytes:" << nBytes << "Unicode:" << u << "ulen:" << uLen << "render:" << state->getRender();
 	double x1, y1, x2, y2;
 	updateFont(state);
 	if (!m_font)
@@ -3221,7 +3240,7 @@
 	// TODO Implement the clipping operations. At least the characters are shown.
 	int textRenderingMode = state->getRender();
 	// Invisible or only used for clipping
-	if (textRenderingMode == 3 || textRenderingMode == 7)
+	if (textRenderingMode == 3)
 		return;
 	if (textRenderingMode < 8)
 	{
@@ -3258,7 +3277,14 @@
 			FPointArray textPath;
 			textPath.fromQPainterPath(qPath);
 			FPoint wh = textPath.widthHeight();
-			if ((textPath.size() > 3) && ((wh.x() != 0.0) || (wh.y() != 0.0)))
+			if (textRenderingMode > 3) {
+				QTransform mm;
+				mm.scale(1, -1);
+				mm.translate(x, -y);
+				// Remember the glyph for later clipping
+ 				m_clipTextPath.addPath(m_ctm.map(mm.map(qPath)));
+			}
+			if ((textPath.size() > 3) && ((wh.x() != 0.0) || (wh.y() != 0.0)) && (textRenderingMode != 7))
 			{
 				int z = m_doc->itemAdd(PageItem::Polygon, PageItem::Unspecified, xCoor, yCoor, 10, 10, 0, CommonStrings::None, CommonStrings::None);
 				PageItem* ite = m_doc->Items->at(z);
@@ -3374,7 +3400,12 @@
 
 void SlaOutputDev::endTextObject(GfxState *state)
 {
-//	qDebug() << "End Text Object";
+//	qDebug() << "SlaOutputDev::endTextObject";
+	if (!m_clipTextPath.isEmpty())
+	{
+		m_currentClipPath = intersection(m_currentClipPath, m_clipTextPath);
+		m_clipTextPath = QPainterPath();
+	}
 	if (m_groupStack.count() != 0)
 	{
 		groupEntry gElements = m_groupStack.pop();
Index: scribus/plugins/import/pdf/slaoutput.h
===================================================================
--- scribus/plugins/import/pdf/slaoutput.h	(Revision 23587)
+++ scribus/plugins/import/pdf/slaoutput.h	(Arbeitskopie)
@@ -324,6 +324,8 @@
 	// rule to use.
 	QPainterPath m_currentClipPath;
 	QStack<QPainterPath> m_clipPaths;
+	// Collect the paths of character glyphs for clipping of a whole text group.
+	QPainterPath  m_clipTextPath;
 
 	struct groupEntry
 	{
add_text_clip.diff (5,092 bytes)   

jghali

2020-04-11 13:58

administrator   ~0047510

Applied, thanks!

Issue History

Date Modified Username Field Change
2020-04-11 13:25 Pontobart New Issue
2020-04-11 13:25 Pontobart File Added: add_text_clip.diff
2020-04-11 13:58 jghali Assigned To => jghali
2020-04-11 13:58 jghali Status new => resolved
2020-04-11 13:58 jghali Resolution open => fixed
2020-04-11 13:58 jghali Fixed in Version => 1.5.6.svn
2020-04-11 13:58 jghali Note Added: 0047510
2020-08-11 20:56 cbradney Status resolved => closed