r19942 by fschmid - Part of #12929 "Problems with EMF Importer", fixed incorrect clipping handling.

scribus-commit scribus-commit at lists.scribus.net
Sat Mar 21 09:25:46 UTC 2015


Author: fschmid
Date: Sat Mar 21 09:25:46 2015
New Revision: 19942

URL: http://scribus.net/websvn/listing.php?repname=Scribus&sc=1&rev=19942
Log:
Part of #12929 "Problems with EMF Importer", fixed incorrect clipping handling.

Modified:
    trunk/Scribus/scribus/plugins/import/emf/importemf.cpp
    trunk/Scribus/scribus/plugins/import/emf/importemf.h

Modified: trunk/Scribus/scribus/plugins/import/emf/importemf.cpp
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=19942&path=/trunk/Scribus/scribus/plugins/import/emf/importemf.cpp
==============================================================================
--- trunk/Scribus/scribus/plugins/import/emf/importemf.cpp (original)
+++ trunk/Scribus/scribus/plugins/import/emf/importemf.cpp Sat Mar 21 09:25:46 2015
@@ -865,8 +865,10 @@
 							ds >> sign >> vers >> bytes >> m_records;
 							bBoxDev = QRectF(QPointF(bLeft, bTop), QPointF(bRight, bBottom)).normalized();
 							bBoxMM = QRectF(QPointF(pLeft, pTop), QPointF(pRight, pBottom)).normalized();
-							dpiX = bBoxDev.width() / (bBoxMM.width() / 100.0) * 25.4;
-							dpiY = bBoxDev.height() / (bBoxMM.height() / 100.0) * 25.4;
+						//	dpiX = bBoxDev.width() / (bBoxMM.width() / 100.0) * 25.4;
+						//	dpiY = bBoxDev.height() / (bBoxMM.height() / 100.0) * 25.4;
+							dpiX = bRight / (pRight / 100.0) * 25.4;
+							dpiY = bBottom / (pBottom / 100.0) * 25.4;
 							b = bBoxMM.width() / 1000.0 / 2.54 * 72.0;
 							h = bBoxMM.height() / 1000.0 / 2.54 * 72.0;
 							x = bBoxMM.x() / 1000.0 / 2.54 * 72.0;
@@ -962,6 +964,7 @@
 	currentDC.Coords.svgInit();
 	currentDC.clipPath.resize(0);
 	currentDC.clipPath.svgInit();
+	currentDC.clipValid = false;
 	currentDC.fontSize = 12;
 	currentDC.fontName = "Arial";
 	currentDC.fontRotation = 0;
@@ -1038,6 +1041,7 @@
 	sty.styType = U_OT_Pen;
 	emfStyleMap.insert(U_DC_PEN, sty);
 	emfStyleMapEMP.clear();
+	clipGroup = NULL;
 	if(progressDialog)
 	{
 		progressDialog->setOverallProgress(2);
@@ -1172,6 +1176,7 @@
 						break;
 					case U_EMR_RESTOREDC:
 						{
+							invalidateClipGroup();
 							qint32 drop;
 							ds >> drop;
 							drop = qAbs(drop);
@@ -1182,6 +1187,14 @@
 									currentDC = dcStack.pop();
 									if (dcStack.count() == 0)
 										break;
+								}
+							}
+							if (currentDC.clipPath.count() != 0)
+							{
+								if (checkClip(currentDC.clipPath))
+								{
+									currentDC.clipValid = true;
+									createClipGroup();
 								}
 							}
 						}
@@ -1340,14 +1353,23 @@
 						break;
 					case U_EMR_SELECTCLIPPATH:
 						{
+							invalidateClipGroup();
 							quint32 mode;
 							ds >> mode;
 							if (currentDC.Coords.count() != 0)
-								currentDC.clipPath = currentDC.Coords.copy();
+							{
+								if (checkClip(currentDC.Coords))
+								{
+									currentDC.clipValid = true;
+									currentDC.clipPath = currentDC.Coords.copy();
+									createClipGroup();
+								}
+							}
 						}
 						break;
-				/*	case U_EMR_INTERSECTCLIPRECT:
+					case U_EMR_EXCLUDECLIPRECT:
 						{
+							invalidateClipGroup();
 							QPointF p1 = getPoint(ds, true);
 							QPointF p2 = getPoint(ds, true);
 							FPointArray clipPath;
@@ -1359,7 +1381,59 @@
 							clipPath.svgLineTo(p1.x(), p2.y());
 							clipPath.svgClosePath();
 							if (currentDC.clipPath.isEmpty())
-								currentDC.clipPath = clipPath.copy();
+							{
+								if (checkClip(clipPath))
+								{
+									currentDC.clipPath = clipPath.copy();
+									currentDC.clipValid = true;
+									createClipGroup();
+								}
+							}
+							else
+							{
+								QPainterPath pathN = clipPath.toQPainterPath(true);
+								QPainterPath pathA = currentDC.clipPath.toQPainterPath(true);
+								QPainterPath resultPath = pathA.subtracted(pathN);
+								if (!resultPath.isEmpty())
+								{
+									FPointArray polyline;
+									polyline.resize(0);
+									polyline.fromQPainterPath(resultPath, true);
+									polyline.svgClosePath();
+									if (checkClip(polyline))
+									{
+										currentDC.clipPath = polyline.copy();
+										currentDC.clipValid = true;
+										createClipGroup();
+									}
+								}
+								else
+									currentDC.clipValid = false;
+							}
+						}
+						break;
+					case U_EMR_INTERSECTCLIPRECT:
+						{
+							invalidateClipGroup();
+							QPointF p1 = getPoint(ds, true);
+							QPointF p2 = getPoint(ds, true);
+							FPointArray clipPath;
+							clipPath.resize(0);
+							clipPath.svgInit();
+							clipPath.svgMoveTo(p1.x(), p1.y());
+							clipPath.svgLineTo(p2.x(), p1.y());
+							clipPath.svgLineTo(p2.x(), p2.y());
+							clipPath.svgLineTo(p1.x(), p2.y());
+							clipPath.svgClosePath();
+							if (currentDC.clipPath.isEmpty())
+							{
+								if (checkClip(clipPath))
+								{
+									currentDC.clipPath = clipPath.copy();
+									currentDC.clipValid = true;
+									createClipGroup();
+								}
+							}
 							else
 							{
 								QPainterPath pathN = clipPath.toQPainterPath(true);
@@ -1371,11 +1445,18 @@
 									polyline.resize(0);
 									polyline.fromQPainterPath(resultPath, true);
 									polyline.svgClosePath();
-									currentDC.clipPath = polyline.copy();
+									if (checkClip(polyline))
+									{
+										currentDC.clipPath = polyline.copy();
+										currentDC.clipValid = true;
+										createClipGroup();
+									}
 								}
+								else
+									currentDC.clipValid = false;
 							}
 						}
-						break;*/
+						break;
 					case U_EMR_ABORTPATH:
 						inPath = false;
 						currentDC.Coords.resize(0);
@@ -1601,6 +1682,7 @@
 				qApp->processEvents();
 			}
 		}
+		invalidateClipGroup();
 		if (Elements.count() == 0)
 		{
 			if (importedColors.count() != 0)
@@ -1625,6 +1707,21 @@
 	return true;
 }
 
+bool EmfPlug::checkClip(FPointArray &clip)
+{
+	bool ret = true;
+	QRectF clipRect = clip.toQPainterPath(false).boundingRect();
+	if (clipRect.x() < docX)
+		ret = false;
+	if (clipRect.y() < docY)
+		ret = false;
+	if (clipRect.right() > docX + docWidth + 1)
+		ret = false;
+	if (clipRect.bottom() > docY + docHeight + 1)
+		ret = false;
+	return ret;
+}
+
 void EmfPlug::aligntoQuadWord(QDataStream &ds)
 {
 	if ((ds.device()->pos() % 4) != 0)
@@ -1645,10 +1742,12 @@
 QPointF EmfPlug::convertDevice2Pts(QPointF in)
 {
 	QPointF out;
-	double scaleX = (bBoxMM.width() / 1000.0 / 2.54 * 72.0) / bBoxDev.width(); // Device -> Pts
-	double scaleY = (bBoxMM.height() / 1000.0 / 2.54 * 72.0) / bBoxDev.height(); // Device -> Pts
-	out.setX(in.x() * scaleX);
-	out.setY(in.y() * scaleY);
+//	double scaleX = (bBoxMM.width() / 1000.0 / 2.54 * 72.0) / bBoxDev.width(); // Device -> Pts
+//	double scaleY = (bBoxMM.height() / 1000.0 / 2.54 * 72.0) / bBoxDev.height(); // Device -> Pts
+//	out.setX(in.x() * scaleX);
+//	out.setY(in.y() * scaleY);
+	out.setX(in.x() / dpiX * 72.0);
+	out.setY(in.y() / dpiY * 72.0);
 	return out;
 }
 
@@ -1663,12 +1762,14 @@
 QPointF EmfPlug::convertLogical2Pts(QPointF in)
 {
 	QPointF out;
-	double scaleX = qAbs((bBoxMM.width() / 1000.0 / 2.54 * 72.0) / bBoxDev.width()); // Device -> Pts
-	double scaleY = qAbs((bBoxMM.height() / 1000.0 / 2.54 * 72.0) / bBoxDev.height()); // Device -> Pts
+//	double scaleX = qAbs((bBoxMM.width() / 1000.0 / 2.54 * 72.0) / bBoxDev.width()); // Device -> Pts
+//	double scaleY = qAbs((bBoxMM.height() / 1000.0 / 2.54 * 72.0) / bBoxDev.height()); // Device -> Pts
 	if (currentDC.m_mapMode == 1)
 	{
-		out.setX(in.x() * scaleX);
-		out.setY(in.y() * scaleY);
+	//	out.setX(in.x() * scaleX);
+	//	out.setY(in.y() * scaleY);
+		out.setX(in.x() / dpiX * 72.0);
+		out.setY(in.y() / dpiY * 72.0);
 	}
 	else if (currentDC.m_mapMode == 2)
 	{
@@ -1700,8 +1801,12 @@
 		double ratioX = viewPextendX / static_cast<double>(winPextendX); // Logical --> Device
 		double ratioY = viewPextendY / static_cast<double>(winPextendY); // Logical --> Device
 		// logic --> device --> pts
-		out.setX(in.x() * ratioX * scaleX);
-		out.setY(in.y() * ratioY * scaleY);
+	//	out.setX(in.x() * ratioX * scaleX);
+	//	out.setY(in.y() * ratioY * scaleY);
+		out.setX(in.x() * ratioX);
+		out.setY(in.y() * ratioY);
+		out.setX(out.x() / dpiX * 72.0);
+		out.setY(out.y() / dpiY * 72.0);
 	}
 	return out;
 }
@@ -2214,54 +2319,54 @@
 			}
 		}
 	}
-	if (inEMFPlus)
-	{
-		if ((currentDC.brushStyle == U_BT_PathGradient) || (currentDC.brushStyle == U_BT_LinearGradient))
-		{
-			if ((!currentDC.clipPath.isEmpty()) && (ite->itemType() != PageItem::ImageFrame))
-			{
-				PageItem *iteG;
-				QList<PageItem*> gElements;
-				gElements.append(ite);
-				tmpSel->clear();
-				tmpSel->addItem(ite, true);
-				iteG = m_Doc->groupObjectsSelection(tmpSel);
-				iteG->setTextFlowMode(PageItem::TextFlowUsesBoundingBox);
-				double oldX = iteG->xPos();
-				double oldY = iteG->yPos();
-				double oldW = iteG->width();
-				double oldH = iteG->height();
-				double oldgW = iteG->groupWidth;
-				double oldgH = iteG->groupHeight;
-				iteG->PoLine = currentDC.clipPath.copy();
-				iteG->PoLine.translate(baseX, baseY);
-				FPoint xy = getMinClipF(&iteG->PoLine);
-				iteG->setXYPos(xy.x(), xy.y(), true);
-				iteG->PoLine.translate(-xy.x(), -xy.y());
-				FPoint whi = getMaxClipF(&iteG->PoLine);
-				iteG->setWidthHeight(whi.x(),whi.y());
-				iteG->groupWidth = oldgW * (iteG->width() / oldW);
-				iteG->groupHeight = oldgH * (iteG->height() / oldH);
-				double dx = (iteG->xPos() - oldX) / (iteG->width() / iteG->groupWidth);
-				double dy = (iteG->yPos() - oldY) / (iteG->height() / iteG->groupHeight);
-				for (int em = 0; em < iteG->groupItemList.count(); ++em)
-				{
-					PageItem* embedded = iteG->groupItemList.at(em);
-					embedded->moveBy(-dx, -dy, true);
-					m_Doc->setRedrawBounding(embedded);
-					embedded->OwnPage = m_Doc->OnPage(embedded);
-				}
-				iteG->ClipEdited = true;
-				iteG->OldB2 = ite->width();
-				iteG->OldH2 = ite->height();
-				iteG->Clip = FlattenPath(iteG->PoLine, iteG->Segments);
-				iteG->updateGradientVectors();
-				ite = iteG;
-				tmpSel->clear();
-			}
-		}
-	}
-	Elements.append(ite);
+	if (clipGroup != NULL)
+	{
+		QList<PageItem*> itemList;
+		itemList.append(ite);
+		m_Doc->groupObjectsToItem(clipGroup, itemList);
+	}
+	else
+		Elements.append(ite);
+}
+
+void EmfPlug::invalidateClipGroup()
+{
+	if (clipGroup != NULL)
+	{
+		if (clipGroup->asGroupFrame()->groupItemList.count() == 0)
+		{
+			Elements.removeAll(clipGroup);
+			m_Doc->Items->removeAll(clipGroup);
+			delete clipGroup;
+		}
+	}
+	clipGroup = NULL;
+}
+
+void EmfPlug::createClipGroup()
+{
+	if (currentDC.clipValid)
+	{
+		int z = m_Doc->itemAdd(PageItem::Group, PageItem::Unspecified, baseX, baseY, 10, 10, 0, CommonStrings::None, CommonStrings::None, true);
+		PageItem* ite = m_Doc->Items->at(z);
+		ite->PoLine = currentDC.clipPath.copy();
+		ite->setFillEvenOdd(false);
+		ite->ClipEdited = true;
+		ite->FrameType = 3;
+		FPoint wh = getMaxClipF(&ite->PoLine);
+		ite->setWidthHeight(wh.x(),wh.y());
+		ite->setTextFlowMode(PageItem::TextFlowDisabled);
+		m_Doc->AdjustItemSize(ite, true);
+		ite->moveBy(-docX, -docY, true);
+		ite->moveBy(-currentDC.winOrigin.x(), -currentDC.winOrigin.y());
+		ite->OldB2 = ite->width();
+		ite->OldH2 = ite->height();
+		ite->updateClip();
+		ite->OwnPage = m_Doc->OnPage(ite);
+		m_Doc->GroupOnPage(ite);
+		clipGroup = ite;
+		Elements.append(ite);
+	}
 }
 
 void EmfPlug::handleComment(QDataStream &ds)
@@ -2835,7 +2940,7 @@
 			ite->isTempFile = true;
 			ite->AspectRatio = false;
 			ite->ScaleType   = false;
-			if (currentDC.clipPath.count() != 0)
+			if (currentDC.clipValid)
 			{
 				FPointArray cp = currentDC.clipPath.copy();
 				cp.translate(baseX, baseY);
@@ -3319,6 +3424,7 @@
 
 void EmfPlug::handleSetClipRegion(QDataStream &ds)
 {
+	invalidateClipGroup();
 	quint32 dummy, mode, countRects;
 	ds >> dummy >> mode;
 	ds >> dummy >> dummy >> countRects;
@@ -3400,6 +3506,8 @@
 				emfPlusDual = (flagsH == 1);
 				dsEmf >> dummy >> dummy;
 				dsEmf >> EmfPdpiX >> EmfPdpiY;
+			//	dpiX = EmfPdpiX;
+			//	dpiY = EmfPdpiY;
 				break;
 			case U_PMR_ENDOFFILE:
 				inEMFPlus = false;
@@ -3480,9 +3588,18 @@
 				dcStackEMP.insert(dummy, currentDC);
 				break;
 			case U_PMR_RESTORE:
+				invalidateClipGroup();
 				dsEmf >> dummy;
 				if (dcStackEMP.contains(dummy))
 					currentDC = dcStackEMP[dummy];
+				if (currentDC.clipPath.count() != 0)
+				{
+					if (checkClip(currentDC.clipPath))
+					{
+						currentDC.clipValid = true;
+						createClipGroup();
+					}
+				}
 				break;
 			case U_PMR_SETWORLDTRANSFORM:
 				dsEmf >> m11 >> m12 >> m21 >> m22 >> dx >> dy;
@@ -3530,16 +3647,20 @@
 				dsEmf >> emfPlusScale;
 				break;
 			case U_PMR_OFFSETCLIP:
-				if (!currentDC.clipPath.isEmpty())
+				if (currentDC.clipValid)
 				{
 					double dx = getEMFPDistance(dsEmf, false);
 					double dy = getEMFPDistance(dsEmf, false);
 					currentDC.clipPath.translate(dx, dy);
+					invalidateClipGroup();
+					createClipGroup();
 				}
 				break;
 			case U_PMR_RESETCLIP:
 				currentDC.clipPath.resize(0);
 				currentDC.clipPath.svgInit();
+				currentDC.clipValid = false;
+				invalidateClipGroup();
 				break;
 			case U_PMR_SETCLIPRECT:
 				handleEMFPSetClipRect(dsEmf, flagsL);
@@ -4860,6 +4981,7 @@
 
 void EmfPlug::handleEMFPSetClipRect(QDataStream &ds, quint8 flagsL)
 {
+	invalidateClipGroup();
 	quint8 mode = flagsL & 0x0F;
 	QPolygonF rect = getEMFPRect(ds, false);
 	FPointArray clipPath;
@@ -4870,8 +4992,15 @@
 	clipPath.svgLineTo(rect[2].x(), rect[2].y());
 	clipPath.svgLineTo(rect[3].x(), rect[3].y());
 	clipPath.svgClosePath();
-	if ((mode == 0) || (currentDC.clipPath.isEmpty()))
-		currentDC.clipPath = clipPath.copy();
+	if ((mode == 0) || (!currentDC.clipValid))
+	{
+		if (checkClip(clipPath))
+		{
+			currentDC.clipPath = clipPath.copy();
+			currentDC.clipValid = true;
+			createClipGroup();
+		}
+	}
 	else
 	{
 		QPainterPath pathN = clipPath.toQPainterPath(true);
@@ -4894,24 +5023,40 @@
 			polyline.resize(0);
 			polyline.fromQPainterPath(resultPath, true);
 			polyline.svgClosePath();
-			currentDC.clipPath = polyline.copy();
-		}
+			if (checkClip(polyline))
+			{
+				currentDC.clipPath = polyline.copy();
+				currentDC.clipValid = true;
+				createClipGroup();
+			}
+		}
+		else
+			currentDC.clipValid = false;
 	}
 }
 
 void EmfPlug::handleEMFPSetClipRegion(QDataStream &ds, quint8 flagsL, quint8 flagsH)
 {
+	invalidateClipGroup();
 	if (emfStyleMapEMP.contains(flagsH))
 	{
 		if (emfStyleMapEMP[flagsH].Coords.isEmpty())
 		{
 			currentDC.clipPath.resize(0);
 			currentDC.clipPath.svgInit();
+			currentDC.clipValid = false;
 			return;
 		}
 		quint8 mode = flagsL & 0x0F;
-		if ((mode == 0) || (currentDC.clipPath.isEmpty()))
-			currentDC.clipPath = emfStyleMapEMP[flagsH].Coords.copy();
+		if ((mode == 0) || (!currentDC.clipValid))
+		{
+			if (checkClip(emfStyleMapEMP[flagsH].Coords))
+			{
+				currentDC.clipPath = emfStyleMapEMP[flagsH].Coords.copy();
+				currentDC.clipValid = true;
+				createClipGroup();
+			}
+		}
 		else
 		{
 			FPointArray clipPath = emfStyleMapEMP[flagsH].Coords.copy();
@@ -4935,24 +5080,40 @@
 				polyline.resize(0);
 				polyline.fromQPainterPath(resultPath, true);
 				polyline.svgClosePath();
-				currentDC.clipPath = polyline.copy();
-			}
+				if (checkClip(polyline))
+				{
+					currentDC.clipPath = polyline.copy();
+					currentDC.clipValid = true;
+					createClipGroup();
+				}
+			}
+			else
+				currentDC.clipValid = false;
 		}
 	}
 	else
 	{
 		currentDC.clipPath.resize(0);
 		currentDC.clipPath.svgInit();
+		currentDC.clipValid = false;
 	}
 }
 
 void EmfPlug::handleEMFPSetClipPath(QDataStream &ds, quint8 flagsL, quint8 flagsH)
 {
+	invalidateClipGroup();
 	if (emfStyleMapEMP.contains(flagsH))
 	{
 		quint8 mode = flagsL & 0x0F;
-		if ((mode == 0) || (currentDC.clipPath.isEmpty()))
-			currentDC.clipPath = emfStyleMapEMP[flagsH].Coords.copy();
+		if ((mode == 0) || (!currentDC.clipValid))
+		{
+			if (checkClip(emfStyleMapEMP[flagsH].Coords))
+			{
+				currentDC.clipPath = emfStyleMapEMP[flagsH].Coords.copy();
+				currentDC.clipValid = true;
+				createClipGroup();
+			}
+		}
 		else
 		{
 			FPointArray clipPath = emfStyleMapEMP[flagsH].Coords.copy();
@@ -4976,8 +5137,15 @@
 				polyline.resize(0);
 				polyline.fromQPainterPath(resultPath, true);
 				polyline.svgClosePath();
-				currentDC.clipPath = polyline.copy();
-			}
+				if (checkClip(polyline))
+				{
+					currentDC.clipPath = polyline.copy();
+					currentDC.clipValid = true;
+					createClipGroup();
+				}
+			}
+			else
+				currentDC.clipValid = false;
 		}
 	}
 }
@@ -5534,7 +5702,7 @@
 					m_Doc->loadPict(fileName, ite);
 					ite->setImageScalingMode(false, false);
 					ite->updateClip();
-					if (currentDC.clipPath.count() != 0)
+					if (currentDC.clipValid)
 					{
 						FPointArray cp = currentDC.clipPath.copy();
 						cp.translate(baseX, baseY);

Modified: trunk/Scribus/scribus/plugins/import/emf/importemf.h
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=19942&path=/trunk/Scribus/scribus/plugins/import/emf/importemf.h
==============================================================================
--- trunk/Scribus/scribus/plugins/import/emf/importemf.h (original)
+++ trunk/Scribus/scribus/plugins/import/emf/importemf.h Sat Mar 21 09:25:46 2015
@@ -148,6 +148,7 @@
 	void        parseHeader(QString fName, double &x, double &y, double &b, double &h);
 	bool        convert(QString fn);
 	// Common functions
+	bool        checkClip(FPointArray &clip);
 	void        aligntoQuadWord(QDataStream &ds);
 	double      convertDevice2Pts(double in);
 	QPointF     convertDevice2Pts(QPointF in);
@@ -161,6 +162,8 @@
 	void        setWTransform(QTransform mm, quint32 how);
 	QPointF     intersectBoundingRect(PageItem *item, QLineF gradientVector);
 	void        finishItem(PageItem* ite, bool fill = true);
+	void        invalidateClipGroup();
+	void        createClipGroup();
 	// Functions for normal EMF Files
 	void        handleComment(QDataStream &ds);
 	void        handleEllipse(QDataStream &ds);
@@ -285,6 +288,7 @@
 		quint32          vAlign;
 		quint32          fontUnit;
 		bool             verticalText;
+		bool             clipValid;
 	};
 	QStack<dcState> dcStack;
 	QHash<quint32, dcState> dcStackEMP;
@@ -292,6 +296,7 @@
 	QHash<quint32, emfStyle> emfStyleMap;
 	QHash<quint32, emfStyle> emfStyleMapEMP;
 	QList<PageItem*> Elements;
+	PageItem* clipGroup;
 	double docWidth;
 	double docHeight;
 	double baseX, baseY;




More information about the scribus-commit mailing list