diff options
author | jaseg <git@jaseg.de> | 2021-08-29 16:27:23 +0200 |
---|---|---|
committer | jaseg <git@jaseg.de> | 2021-09-29 16:37:59 +0200 |
commit | 7eb0b9d7e42a20b85bd7afbfe3d33d9dd5fa5794 (patch) | |
tree | 5ac1f274b0c933234535c6b8f19a8d270f9e2d83 | |
parent | c58b6573f2a0694c0c1942e7c36704e0517ced19 (diff) | |
download | gerbolyze-7eb0b9d7e42a20b85bd7afbfe3d33d9dd5fa5794.tar.gz gerbolyze-7eb0b9d7e42a20b85bd7afbfe3d33d9dd5fa5794.tar.bz2 gerbolyze-7eb0b9d7e42a20b85bd7afbfe3d33d9dd5fa5794.zip |
svg-flatten: Add wasmtime support
-rw-r--r-- | svg-flatten/Makefile | 60 | ||||
-rw-r--r-- | svg-flatten/src/main.cpp | 48 | ||||
-rw-r--r-- | svg-flatten/src/svg_import_util.cpp | 7 | ||||
-rw-r--r-- | svg-flatten/src/util.cpp | 12 | ||||
l--------- | svg-flatten/upstream | 1 | ||||
-rw-r--r-- | upstream/clipper-6.4.2/cpp/clipper.cpp | 112 | ||||
-rw-r--r-- | upstream/clipper-6.4.2/cpp/clipper.hpp | 12 |
7 files changed, 170 insertions, 82 deletions
diff --git a/svg-flatten/Makefile b/svg-flatten/Makefile index fc5820f..94dab9b 100644 --- a/svg-flatten/Makefile +++ b/svg-flatten/Makefile @@ -6,10 +6,17 @@ PKG_CONFIG ?= pkg-config PYTHON3 ?= python3 BUILDDIR ?= build +CACHEDIR ?= cache PREFIX ?= /usr/local -UPSTREAM_DIR ?= ../upstream +UPSTREAM_DIR ?= upstream -SOURCES := src/svg_color.cpp \ +WASI_SDK ?= wasi-sdk-11.0 +WASI_SDK_URL ?= https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-11/wasi-sdk-11.0-linux.tar.gz +WASI_SDK_PATH ?= $(CACHEDIR)/$(WASI_SDK) +WASI_CXX ?= $(WASI_SDK_PATH)/bin/clang++ --sysroot=$(WASI_SDK_PATH)/share/wasi-sysroot + +SOURCES := \ + src/svg_color.cpp \ src/svg_doc.cpp \ src/svg_geom.cpp \ src/svg_import_util.cpp \ @@ -47,28 +54,47 @@ STB_INCLUDES ?= -isystem$(UPSTREAM_DIR)/stb INCLUDES := -Iinclude -Isrc $(CLIPPER_INCLUDES) $(VORONOI_INCLUDES) $(POISSON_INCLUDES) $(BASE64_INCLUDES) $(ARGAGG_INCLUDES) $(CAVC_INCLUDES) $(SUBPROCESS_INCLUDES) $(MINUNIT_INCLUDES) $(STB_INCLUDES) CXXFLAGS := -std=c++2a -g -Wall -Wextra -O2 -LDFLAGS := -lm -lstdc++ -lstdc++fs # for debian's ancient compilers +LDFLAGS := -lm -lstdc++ -PKG_CONFIG_DEPS := ifdef USE_SYSTEM_PUGIXML - CXXFLAGS += $(shell $(PKG_CONFIG) --cflags pugixml) - LDFLAGS += $(shell $(PKG_CONFIG) --libs pugixml) + HOST_CXXFLAGS := $(CXXFLAGS) $(shell $(PKG_CONFIG) --cflags pugixml) + HOST_LDFLAGS := $(LDFLAGS) $(shell $(PKG_CONFIG) --libs pugixml) + HOST_SOURCES := $(SOURCES) + HOST_INCLUDES := $(INCLUDES) else - SOURCES += $(PUGIXML_SOURCES) - INCLUDES += $(PUGIXML_INCLUDES) + HOST_CXXFLAGS := $(CXXFLAGS) + HOST_LDFLAGS := $(LDFLAGS) + HOST_SOURCES := $(SOURCES) $(PUGIXML_SOURCES) + HOST_INCLUDES := $(INCLUDES) $(PUGIXML_INCLUDES) endif -TARGET := svg-flatten +HOST_LDFLAGS += -lstdc++fs # for debian's ancient compilers + +WASI_CXXFLAGS ?= -DNOFORK -DNOTHROW -DWASI -DPUGIXML_NO_EXCEPTIONS -fno-exceptions $(CXXFLAGS) + +BINARY := svg-flatten + +all: $(BUILDDIR)/$(BINARY) -all: $(BUILDDIR)/$(TARGET) +$(CACHEDIR)/$(WASI_SDK): + mkdir -p $(dir $@) + cd $(dir $@); curl -L ${WASI_SDK_URL} | tar xzf - -$(BUILDDIR)/%.o: %.cpp +$(BUILDDIR)/wasi/%.o: %.cpp $(CACHEDIR)/$(WASI_SDK) @mkdir -p $(dir $@) - $(CXX) -c $(CXXFLAGS) $(CXXFLAGS) $(INCLUDES) -o $@ $^ + $(WASI_CXX) -c $(WASI_CXXFLAGS) $(INCLUDES) $(PUGIXML_INCLUDES) -o $@ $< -$(BUILDDIR)/$(TARGET): $(SOURCES:%.cpp=$(BUILDDIR)/%.o) +$(BUILDDIR)/$(BINARY).wasm: $(patsubst %.cpp,$(BUILDDIR)/wasi/%.o,$(SOURCES) $(PUGIXML_SOURCES)) + @mkdir -p $(dir $@) + $(WASI_CXX) $(WASI_CXXFLAGS) -o $@ $^ $(LDFLAGS) + +$(BUILDDIR)/host/%.o: %.cpp + @mkdir -p $(dir $@) + $(CXX) -c $(HOST_CXXFLAGS) $(HOST_CXXFLAGS) $(HOST_INCLUDES) -o $@ $< + +$(BUILDDIR)/$(BINARY): $(HOST_SOURCES:%.cpp=$(BUILDDIR)/host/%.o) @mkdir -p $(dir $@) - $(CXX) $(CXXFLAGS) -o $@ $^ $(LDFLAGS) + $(CXX) $(HOST_CXXFLAGS) -o $@ $^ $(HOST_LDFLAGS) $(BUILDDIR)/nopencv-test: src/test/nopencv_test.cpp src/nopencv.cpp src/util.cpp @mkdir -p $(dir $@) @@ -82,8 +108,12 @@ tests: $(BUILDDIR)/nopencv-test .PHONY: install install: - $(INSTALL) $(BUILDDIR)/$(TARGET) $(PREFIX)/bin + $(INSTALL) $(BUILDDIR)/$(BINARY) $(PREFIX)/bin .PHONY: clean clean: rm -rf $(BUILDDIR) + +.PHONY: mrproper +mrproper: clean + rm -rf $(CACHEDIR) diff --git a/svg-flatten/src/main.cpp b/svg-flatten/src/main.cpp index 8512547..2ebcfe9 100644 --- a/svg-flatten/src/main.cpp +++ b/svg-flatten/src/main.cpp @@ -3,6 +3,7 @@ #include <cstdio> #include <filesystem> #include <iostream> +#include <iomanip> #include <fstream> #include <algorithm> #include <string> @@ -17,6 +18,34 @@ using argagg::parser; using namespace std; using namespace gerbolyze; +string temp_file_path(const char *suffix) { + ifstream rnd; + rnd.open("/dev/urandom", ios::in | ios::binary); + + char fn_buf[8]; + rnd.read(fn_buf, sizeof(fn_buf)); + + if (rnd.rdstate()) { + cerr << "Error getting random data for temporary file name" << endl; + abort(); + } + + ostringstream out; + out << "tmp_"; + for (size_t i=0; i<sizeof(fn_buf); i++) { + out << setfill('0') << setw(2) << setbase(16) << static_cast<int>(fn_buf[i] & 0xff); + } + out << suffix; + + cerr << "out \"" << out.str() << "\"" << endl; +#ifndef WASI + filesystem::path base = filesystem::temp_directory_path(); + return (base / out.str()).native(); +#else + return "/tmp/" + out.str(); +#endif +} + int main(int argc, char **argv) { parser argparser {{ {"help", {"-h", "--help"}, @@ -114,15 +143,7 @@ int main(int argc, char **argv) { << endl; argagg::parser_results args; - try { - args = argparser.parse(argc, argv); - } catch (const std::exception& e) { - argagg::fmt_ostream fmt(cerr); - fmt << usage.str() << argparser << '\n' - << "Encountered exception while parsing arguments: " << e.what() - << '\n'; - return EXIT_FAILURE; - } + args = argparser.parse(argc, argv); if (args["help"]) { argagg::fmt_ostream fmt(cerr); @@ -267,8 +288,8 @@ int main(int argc, char **argv) { transform(ending.begin(), ending.end(), ending.begin(), [](unsigned char c){ return std::tolower(c); }); /* c++ yeah */ } - filesystem::path barf = { filesystem::temp_directory_path() /= (std::tmpnam(nullptr) + string(".svg")) }; - filesystem::path frob = { filesystem::temp_directory_path() /= (std::tmpnam(nullptr) + string(".svg")) }; + string barf = temp_file_path(".svg"); + string frob = temp_file_path(".svg"); bool is_svg = args["force_svg"] || (ending == ".svg" && !args["force_png"]); if (!is_svg) { @@ -352,10 +373,15 @@ int main(int argc, char **argv) { } string dpi_str = to_string(dpi); +#ifndef NOFORK const char *command_line[] = {nullptr, "--keep-named-groups", "--dpi", dpi_str.c_str(), barf.c_str(), frob.c_str(), nullptr}; if (run_cargo_command("usvg", command_line, "USVG")) { return EXIT_FAILURE; } +#else + cerr << "Error: The caller of svg-flatten (you?) must use --no-usvg and run usvg externally since wasi does not yet support fork/exec." << endl; + return EXIT_FAILURE; +#endif } VectorizerSelectorizer vec_sel(vectorizer, args["vectorizer_map"] ? args["vectorizer_map"].as<string>() : ""); diff --git a/svg-flatten/src/svg_import_util.cpp b/svg-flatten/src/svg_import_util.cpp index cb60482..85db3ad 100644 --- a/svg-flatten/src/svg_import_util.cpp +++ b/svg-flatten/src/svg_import_util.cpp @@ -61,6 +61,11 @@ string gerbolyze::parse_data_iri(const string &data_url) { size_t b64_begin = data_url.find_first_not_of(" ", foo + strlen("base64,")); assert(b64_begin != string::npos); - return base64_decode(data_url.substr(b64_begin)); + bool err_out; + string out = base64_decode(data_url.substr(b64_begin), false, &err_out); + + if (err_out) + return ""; + return out; } diff --git a/svg-flatten/src/util.cpp b/svg-flatten/src/util.cpp index e88f4e9..d9a5a09 100644 --- a/svg-flatten/src/util.cpp +++ b/svg-flatten/src/util.cpp @@ -1,16 +1,19 @@ -#include <pwd.h> #include <sys/types.h> #include <string> #include <iostream> +#ifndef NOFORK +#include <pwd.h> #include <subprocess.h> +#endif #include <filesystem> #include "util.h" using namespace std; +#ifndef NOFORK int gerbolyze::run_cargo_command(const char *cmd_name, const char *cmdline[], const char *envvar) { const char *homedir; if ((homedir = getenv("HOME")) == NULL) { @@ -81,4 +84,11 @@ int gerbolyze::run_cargo_command(const char *cmd_name, const char *cmdline[], co return 0; } +#else +int gerbolyze::run_cargo_command(const char *cmd_name, const char *cmdline[], const char *envvar) { + (void) cmd_name, (void) cmdline, (void) envvar; + cerr << "Error: Cannot spawn " << cmd_name << " subprocess since binary was built with fork/exec disabled (-DNOFORK=1)" << endl; + return EXIT_FAILURE; +} +#endif diff --git a/svg-flatten/upstream b/svg-flatten/upstream new file mode 120000 index 0000000..f84a283 --- /dev/null +++ b/svg-flatten/upstream @@ -0,0 +1 @@ +../upstream
\ No newline at end of file diff --git a/upstream/clipper-6.4.2/cpp/clipper.cpp b/upstream/clipper-6.4.2/cpp/clipper.cpp index d0e5ba2..42aaec7 100644 --- a/upstream/clipper-6.4.2/cpp/clipper.cpp +++ b/upstream/clipper-6.4.2/cpp/clipper.cpp @@ -39,6 +39,9 @@ *******************************************************************************/
#include "clipper.hpp"
+#ifdef NOTHROW
+#include <iostream>
+#endif
#include <cmath>
#include <vector>
#include <algorithm>
@@ -133,6 +136,18 @@ struct LocMinSorter //------------------------------------------------------------------------------
//------------------------------------------------------------------------------
+inline void panic(const char *msg);
+inline void panic(const char *msg) {
+#ifdef NOTHROW
+ std::cerr << "Fatal clipper exception: " << msg << std::endl;
+ abort();
+#else
+ throw clipperException(msg);
+#endif
+}
+
+//------------------------------------------------------------------------------
+
inline cInt Round(double val)
{
if ((val < 0)) return static_cast<cInt>(val - 0.5);
@@ -898,7 +913,7 @@ void RangeTest(const IntPoint& Pt, bool& useFullRange) if (useFullRange)
{
if (Pt.X > hiRange || Pt.Y > hiRange || -Pt.X > hiRange || -Pt.Y > hiRange)
- throw clipperException("Coordinate outside allowed range");
+ panic("Coordinate outside allowed range");
}
else if (Pt.X > loRange|| Pt.Y > loRange || -Pt.X > loRange || -Pt.Y > loRange)
{
@@ -1046,10 +1061,10 @@ bool ClipperBase::AddPath(const Path &pg, PolyType PolyTyp, bool Closed) {
#ifdef use_lines
if (!Closed && PolyTyp == ptClip)
- throw clipperException("AddPath: Open paths must be subject.");
+ panic("AddPath: Open paths must be subject.");
#else
if (!Closed)
- throw clipperException("AddPath: Open paths have been disabled.");
+ panic("AddPath: Open paths have been disabled.");
#endif
int highI = (int)pg.size() -1;
@@ -1062,8 +1077,10 @@ bool ClipperBase::AddPath(const Path &pg, PolyType PolyTyp, bool Closed) bool IsFlat = true;
//1. Basic (first) edge initialization ...
+#ifndef NOTHROW
try
{
+#endif
edges[1].Curr = pg[1];
RangeTest(pg[0], m_UseFullRange);
RangeTest(pg[highI], m_UseFullRange);
@@ -1074,12 +1091,14 @@ bool ClipperBase::AddPath(const Path &pg, PolyType PolyTyp, bool Closed) RangeTest(pg[i], m_UseFullRange);
InitEdge(&edges[i], &edges[i+1], &edges[i-1], pg[i]);
}
+#ifndef NOTHROW
}
catch(...)
{
delete [] edges;
throw; //range test fails
}
+#endif
TEdge *eStart = &edges[0];
//2. Remove duplicate vertices, and (when closed) collinear edges ...
@@ -1439,10 +1458,10 @@ void ClipperBase::SwapPositionsInAEL(TEdge *Edge1, TEdge *Edge2) }
//------------------------------------------------------------------------------
-void ClipperBase::UpdateEdgeIntoAEL(TEdge *&e)
+void ClipperBase::UpdateEdgeIntoAEL(TEdge *&e, bool *err_out)
{
if (!e->NextInLML)
- throw clipperException("UpdateEdgeIntoAEL: invalid call");
+ *err_out = true;
e->NextInLML->OutIdx = e->OutIdx;
TEdge* AelPrev = e->PrevInAEL;
@@ -1510,7 +1529,7 @@ bool Clipper::Execute(ClipType clipType, Paths &solution, {
if( m_ExecuteLocked ) return false;
if (m_HasOpenPaths)
- throw clipperException("Error: PolyTree struct is needed for open path clipping.");
+ panic("Error: PolyTree struct is needed for open path clipping.");
m_ExecuteLocked = true;
solution.resize(0);
m_SubjFillType = subjFillType;
@@ -1559,36 +1578,30 @@ void Clipper::FixHoleLinkage(OutRec &outrec) bool Clipper::ExecuteInternal()
{
- bool succeeded = true;
- try {
- Reset();
- m_Maxima = MaximaList();
- m_SortedEdges = 0;
+ bool error = false;
+ Reset();
+ m_Maxima = MaximaList();
+ m_SortedEdges = 0;
- succeeded = true;
- cInt botY, topY;
- if (!PopScanbeam(botY)) return false;
- InsertLocalMinimaIntoAEL(botY);
- while (PopScanbeam(topY) || LocalMinimaPending())
+ error = false;
+ cInt botY, topY;
+ if (!PopScanbeam(botY)) return false;
+ InsertLocalMinimaIntoAEL(botY);
+ while (PopScanbeam(topY) || LocalMinimaPending())
+ {
+ ProcessHorizontals(&error);
+ ClearGhostJoins();
+ if (!ProcessIntersections(topY, &error))
{
- ProcessHorizontals();
- ClearGhostJoins();
- if (!ProcessIntersections(topY))
- {
- succeeded = false;
- break;
- }
- ProcessEdgesAtTopOfScanbeam(topY);
- botY = topY;
- InsertLocalMinimaIntoAEL(botY);
+ error = true;
+ break;
}
- }
- catch(...)
- {
- succeeded = false;
+ ProcessEdgesAtTopOfScanbeam(topY, &error);
+ botY = topY;
+ InsertLocalMinimaIntoAEL(botY);
}
- if (succeeded)
+ if (!error)
{
//fix orientations ...
for (PolyOutList::size_type i = 0; i < m_PolyOuts.size(); ++i)
@@ -1617,7 +1630,7 @@ bool Clipper::ExecuteInternal() ClearJoins();
ClearGhostJoins();
- return succeeded;
+ return !error;
}
//------------------------------------------------------------------------------
@@ -2509,11 +2522,11 @@ OutPt* Clipper::GetLastOutPt(TEdge *e) }
//------------------------------------------------------------------------------
-void Clipper::ProcessHorizontals()
+void Clipper::ProcessHorizontals(bool *err_out)
{
TEdge* horzEdge;
while (PopEdgeFromSEL(horzEdge))
- ProcessHorizontal(horzEdge);
+ ProcessHorizontal(horzEdge, err_out);
}
//------------------------------------------------------------------------------
@@ -2633,7 +2646,7 @@ void GetHorzDirection(TEdge& HorzEdge, Direction& Dir, cInt& Left, cInt& Right) * the AEL. These 'promoted' edges may in turn intersect [%] with other HEs. *
*******************************************************************************/
-void Clipper::ProcessHorizontal(TEdge *horzEdge)
+void Clipper::ProcessHorizontal(TEdge *horzEdge, bool *err_out)
{
Direction dir;
cInt horzLeft, horzRight;
@@ -2762,7 +2775,7 @@ void Clipper::ProcessHorizontal(TEdge *horzEdge) //Break out of loop if HorzEdge.NextInLML is not also horizontal ...
if (!horzEdge->NextInLML || !IsHorizontal(*horzEdge->NextInLML)) break;
- UpdateEdgeIntoAEL(horzEdge);
+ UpdateEdgeIntoAEL(horzEdge, err_out);
if (horzEdge->OutIdx >= 0) AddOutPt(horzEdge, horzEdge->Bot);
GetHorzDirection(*horzEdge, dir, horzLeft, horzRight);
@@ -2791,7 +2804,7 @@ void Clipper::ProcessHorizontal(TEdge *horzEdge) if(horzEdge->OutIdx >= 0)
{
op1 = AddOutPt( horzEdge, horzEdge->Top);
- UpdateEdgeIntoAEL(horzEdge);
+ UpdateEdgeIntoAEL(horzEdge, err_out);
if (horzEdge->WindDelta == 0) return;
//nb: HorzEdge is no longer horizontal here
TEdge* ePrev = horzEdge->PrevInAEL;
@@ -2814,7 +2827,7 @@ void Clipper::ProcessHorizontal(TEdge *horzEdge) }
}
else
- UpdateEdgeIntoAEL(horzEdge);
+ UpdateEdgeIntoAEL(horzEdge, err_out);
}
else
{
@@ -2824,22 +2837,25 @@ void Clipper::ProcessHorizontal(TEdge *horzEdge) }
//------------------------------------------------------------------------------
-bool Clipper::ProcessIntersections(const cInt topY)
+bool Clipper::ProcessIntersections(const cInt topY, bool *err_out)
{
+ (void) err_out;
if( !m_ActiveEdges ) return true;
- try {
+ //try {
BuildIntersectList(topY);
size_t IlSize = m_IntersectList.size();
if (IlSize == 0) return true;
if (IlSize == 1 || FixupIntersectionOrder()) ProcessIntersectList();
else return false;
+ /*
}
catch(...)
{
m_SortedEdges = 0;
DisposeIntersectNodes();
- throw clipperException("ProcessIntersections error");
+ *err_out = true;
}
+ */
m_SortedEdges = 0;
return true;
}
@@ -2954,7 +2970,7 @@ bool Clipper::FixupIntersectionOrder() }
//------------------------------------------------------------------------------
-void Clipper::DoMaxima(TEdge *e)
+void Clipper::DoMaxima(TEdge *e, bool *err_out)
{
TEdge* eMaxPair = GetMaximaPairEx(e);
if (!eMaxPair)
@@ -3002,11 +3018,11 @@ void Clipper::DoMaxima(TEdge *e) DeleteFromAEL(eMaxPair);
}
#endif
- else throw clipperException("DoMaxima error");
+ else *err_out = true;
}
//------------------------------------------------------------------------------
-void Clipper::ProcessEdgesAtTopOfScanbeam(const cInt topY)
+void Clipper::ProcessEdgesAtTopOfScanbeam(const cInt topY, bool *err_out)
{
TEdge* e = m_ActiveEdges;
while( e )
@@ -3025,7 +3041,7 @@ void Clipper::ProcessEdgesAtTopOfScanbeam(const cInt topY) {
if (m_StrictSimple) m_Maxima.push_back(e->Top.X);
TEdge* ePrev = e->PrevInAEL;
- DoMaxima(e);
+ DoMaxima(e, err_out);
if( !ePrev ) e = m_ActiveEdges;
else e = ePrev->NextInAEL;
}
@@ -3034,7 +3050,7 @@ void Clipper::ProcessEdgesAtTopOfScanbeam(const cInt topY) //2. promote horizontal edges, otherwise update Curr.X and Curr.Y ...
if (IsIntermediate(e, topY) && IsHorizontal(*e->NextInLML))
{
- UpdateEdgeIntoAEL(e);
+ UpdateEdgeIntoAEL(e, err_out);
if (e->OutIdx >= 0)
AddOutPt(e, e->Bot);
AddEdgeToSEL(e);
@@ -3072,7 +3088,7 @@ void Clipper::ProcessEdgesAtTopOfScanbeam(const cInt topY) //3. Process horizontals at the Top of the scanbeam ...
m_Maxima.sort();
- ProcessHorizontals();
+ ProcessHorizontals(err_out);
m_Maxima.clear();
//4. Promote intermediate vertices ...
@@ -3084,7 +3100,7 @@ void Clipper::ProcessEdgesAtTopOfScanbeam(const cInt topY) OutPt* op = 0;
if( e->OutIdx >= 0 )
op = AddOutPt(e, e->Top);
- UpdateEdgeIntoAEL(e);
+ UpdateEdgeIntoAEL(e, err_out);
//if output polygons share an edge, they'll need joining later ...
TEdge* ePrev = e->PrevInAEL;
diff --git a/upstream/clipper-6.4.2/cpp/clipper.hpp b/upstream/clipper-6.4.2/cpp/clipper.hpp index df1f813..8e91e81 100644 --- a/upstream/clipper-6.4.2/cpp/clipper.hpp +++ b/upstream/clipper-6.4.2/cpp/clipper.hpp @@ -242,7 +242,7 @@ protected: void DisposeOutRec(PolyOutList::size_type index);
void SwapPositionsInAEL(TEdge *edge1, TEdge *edge2);
void DeleteFromAEL(TEdge *e);
- void UpdateEdgeIntoAEL(TEdge *&e);
+ void UpdateEdgeIntoAEL(TEdge *&e, bool *err_out);
typedef std::vector<LocalMinimum> MinimaList;
MinimaList::iterator m_CurrentLM;
@@ -317,9 +317,9 @@ private: void SwapPositionsInSEL(TEdge *edge1, TEdge *edge2);
bool IsContributing(const TEdge& edge) const;
bool IsTopHorz(const cInt XPos);
- void DoMaxima(TEdge *e);
- void ProcessHorizontals();
- void ProcessHorizontal(TEdge *horzEdge);
+ void DoMaxima(TEdge *e, bool *err_out);
+ void ProcessHorizontals(bool *err_out);
+ void ProcessHorizontal(TEdge *horzEdge, bool *err_out);
void AddLocalMaxPoly(TEdge *e1, TEdge *e2, const IntPoint &pt);
OutPt* AddLocalMinPoly(TEdge *e1, TEdge *e2, const IntPoint &pt);
OutRec* GetOutRec(int idx);
@@ -327,10 +327,10 @@ private: void IntersectEdges(TEdge *e1, TEdge *e2, IntPoint &pt);
OutPt* AddOutPt(TEdge *e, const IntPoint &pt);
OutPt* GetLastOutPt(TEdge *e);
- bool ProcessIntersections(const cInt topY);
+ bool ProcessIntersections(const cInt topY, bool *err_out);
void BuildIntersectList(const cInt topY);
void ProcessIntersectList();
- void ProcessEdgesAtTopOfScanbeam(const cInt topY);
+ void ProcessEdgesAtTopOfScanbeam(const cInt topY, bool *err_out);
void BuildResult(Paths& polys);
void BuildResult2(PolyTree& polytree);
void SetHoleState(TEdge *e, OutRec *outrec);
|