--- 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; +}