src/ldDocument.cc

branch
experimental
changeset 885
9c4fc9b433ae
parent 883
69b8adc9a669
child 889
ba9e4bcc2fcc
--- a/src/ldDocument.cc	Sun Sep 07 04:15:54 2014 +0300
+++ b/src/ldDocument.cc	Sun Sep 07 18:41:23 2014 +0300
@@ -208,6 +208,12 @@
 	}
 }
 
+LDObjectList const& LDDocument::objects()
+{
+	sweepBFC();
+	return m_objects;
+}
+
 // =============================================================================
 //
 QList<LDDocumentPtr> const& LDDocument::explicitDocuments()
@@ -1142,6 +1148,7 @@
 }
 
 // =============================================================================
+// Adds an object at the end of the file.
 //
 int LDDocument::addObject (LDObjectPtr obj)
 {
@@ -1150,6 +1157,7 @@
 	addKnownVertices (obj);
 	obj->setDocument (self());
 	g_win->R()->compileObject (obj);
+	requireBFCSweep();
 	return getObjectCount() - 1;
 }
 
@@ -1162,6 +1170,8 @@
 		if (obj != null)
 			addObject (obj);
 	}
+
+	requireBFCSweep();
 }
 
 // =============================================================================
@@ -1172,8 +1182,8 @@
 	m_objects.insert (pos, obj);
 	obj->setDocument (self());
 	g_win->R()->compileObject (obj);
+	requireBFCSweep();
 	
-
 #ifdef DEBUG
 	if (not isImplicit())
 		dprint ("Inserted object #%1 (%2) at %3\n", obj->id(), obj->typeName(), pos);
@@ -1209,6 +1219,11 @@
 		m_objectVertices.remove (obj);
 	}
 
+	// We only need a sweep if we got rid of a BFC object, no processing is required if a polygon
+	// just got removed.
+	if (obj->type() == OBJ_BFC)
+		requireBFCSweep();
+
 	m_objects.removeAt (idx);
 	obj->setDocument (LDDocumentPtr());
 }
@@ -1252,11 +1267,12 @@
 
 // =============================================================================
 //
-LDObjectPtr LDDocument::getObject (int pos) const
+LDObjectPtr LDDocument::getObject (int pos)
 {
 	if (m_objects.size() <= pos)
 		return LDObjectPtr();
 
+	sweepBFC();
 	return m_objects[pos];
 }
 
@@ -1264,7 +1280,7 @@
 //
 int LDDocument::getObjectCount() const
 {
-	return objects().size();
+	return m_objects.size();
 }
 
 // =============================================================================
@@ -1502,8 +1518,9 @@
 
 // =============================================================================
 //
-const LDObjectList& LDDocument::getSelection() const
+const LDObjectList& LDDocument::getSelection()
 {
+	sweepBFC();
 	return m_sel;
 }
 
@@ -1517,6 +1534,7 @@
 	m_objects[b] = one;
 	m_objects[a] = other;
 	addToHistory (new SwapHistory (one->id(), other->id()));
+	requireBFCSweep();
 }
 
 // =============================================================================
@@ -1549,3 +1567,72 @@
 {
 	m_needVertexMerge = true;
 }
+
+//
+// Sweeps through the file and adjusts the block windings of all objects.
+//
+void LDDocument::sweepBFC()
+{
+	if (not m_needBFCSweep)
+		return;
+
+	QTime t0 (QTime::currentTime());
+	Winding winding (Winding::None);
+	Winding preclip (winding);
+	LDBFCPtr bfc;
+	bool invertnext (false);
+
+	for (LDObjectPtr obj : m_objects)
+	{
+		if (obj->type() == OBJ_BFC)
+		{
+			switch (obj.staticCast<LDBFC>()->statement())
+			{
+			case BFCStatement::CCW:
+			case BFCStatement::CertifyCCW:
+				winding = Winding::CCW;
+				break;
+
+			case BFCStatement::CW:
+			case BFCStatement::CertifyCW:
+				winding = Winding::CW;
+
+			case BFCStatement::NoCertify:
+				winding = Winding::None;
+				break;
+
+			case BFCStatement::NoClip:
+				preclip = winding;
+				winding = Winding::None;
+				break;
+
+			case BFCStatement::InvertNext:
+				invertnext = true;
+				break;
+
+			case BFCStatement::Clip:
+				winding = preclip;
+				break;
+
+			default:
+				break;
+			}
+		}
+		else
+		{
+			Winding objwinding (winding);
+
+			if (invertnext)
+			{
+				invertWinding (objwinding);
+				invertnext = false;
+			}
+
+			print ("%1: BFC sweep: set winding of %2 to %3", getDisplayName(), obj->id(), int (objwinding));
+			obj->setBlockWinding (objwinding);
+		}
+	}
+
+	print ("%1: BFC sweep done in %2ms", getDisplayName(), t0.msecsTo (QTime::currentTime()));
+	m_needBFCSweep = false;
+}

mercurial